我一直试图弄清楚我得到的一系列查询有什么问题,而我现在只是感到困惑。
它应该在一个存储过程中,由GUI应用程序调用。
只有一个“小”问题,首先是一个简单的UPDATE
,然后INSERT
使用带有子选择的SELECT
,最后是另一个UPDATE
。手动运行这些查询我得到的总执行时间为0.057秒,而不是太破旧。
现在,我尝试使用这些查询创建一个存储过程和五个输入变量,我运行此过程并在第一次尝试时花了47.096s,随后调用它显示类似的执行时间(35到50秒)。从MySQL Workbench运行各个查询仍然显示执行时间小于0.1s
这些查询确实没有任何花哨的东西,为什么存储过程需要永久执行而查询本身只需要几分之一秒?我在这里缺少什么样的MySQL特性?
其他测试结果:
似乎如果我在MySQL Workbench中运行查询但是使用变量而不是仅仅将变量的值放在查询中它运行的速度和存储过程一样慢。因此,我尝试将存储过程更改为仅使用静态值而不是变量,突然间它的速度非常快。显然由于某种原因使用变量使得它运行得非常慢(例如,当我在查询中直接使用变量值时,第一个UPDATE
查询从三个变量大约需要0.98s到0.04-0.05s,无论是在存储过程中还是直接运行查询。
所以,问题不在于存储过程,而是与我使用变量有关(这是不可避免的)。
答案 0 :(得分:8)
我遇到了同样的问题。经过一段时间的研究,我发现问题是整理问题,而MySQL正在比较文本。
TL; DR:表是在一个排序规则中创建的,而MySQL“认为”变量是在另一个排序规则中。因此,MySQL无法使用用于查询的索引。
就我而言,该表是使用( latin1 , latin1_swedish_ci )排序规则创建的。为了使MySQL使用索引,我不得不从
更改存储过程中的where
子句
UPDATE ... WHERE mycolumn = myvariable
到
UPDATE ... WHERE mycolumn =
convert(myvariable using latin1) collate latin1_swedish_ci
更改后,存储过程看起来像这样:
CREATE PROCEDURE foo.'bar'()
BEGIN
UPDATE mytable SET mycolumn1 = variable1
WHERE mycolumn2 =
convert(variable2 using latin1) collate latin1_swedish_ci
END;
其中( latin1 , latin1_swedish_ci )与我的 tableA 创建的排序规则相同。
要检查MySQL是否使用索引,您可以更改存储过程以运行explain
语句,如下所示:
CREATE PROCEDURE foo.'bar'()
BEGIN
EXPLAIN SELECT * FROM table WHERE mycolumn2 = variable2
END;
就我而言,explain
结果显示在执行查询期间没有使用索引。
请注意,当您单独运行查询时,MySQL可能会使用索引,但仍然不会在存储过程中对同一查询使用索引,这可能是因为MySQL以某种方式在另一个排序规则中看到变量。
有关排序问题的更多信息,请访问: http://lowleveldesign.wordpress.com/2013/07/19/diagnosing-collation-issue-mysql-stored-procedure/ 备份链接: http://www.codeproject.com/Articles/623272/Diagnosing-a-collation-issue-in-a-MySQL-stored-pro
答案 1 :(得分:3)
我有类似的问题。 运行mysql例程非常慢。 但是一位同事帮助了我。 问题是AUTOCOMMIT是真的; 因此,每次插入和选择都会创建一个完整的事务。 然后我用
运行我的例行程序SET autocommit=0;
开头和
SET autocommit=1;
最后。表现从近500s增加到4s
答案 2 :(得分:0)
提出一个非常有趣和重要的问题。我发现this discussion存储过程可能很慢的一些原因。我有兴趣看到读者对它的反应。
我从交换中获得的主要建议:它有助于添加更多索引。
答案 3 :(得分:0)
由于我不想浪费太多时间试图弄清楚为什么在我的存储过程中使用变量会使它们变得非常慢,所以我决定采用一些人认为非常难看的修复程序。我只是直接从我的应用程序的数据访问层执行每个查询。这不是最漂亮的方式(因为这个应用程序的许多其他东西都使用存储过程),但它可以工作,现在用户不必等待40秒以上的某些操作,因为它们几乎立即发生。
所以,并非真正解决或解释发生了什么,但至少它是有效的。
答案 4 :(得分:0)
我们今天遇到的一些事情使得程序变慢,即使它们作为直接查询运行得非常快,也具有与列名称相同的参数(或者,可能是变量)。简短版本是,不要使用与将在其中使用它的查询中的一列相同的参数名称。例如,如果您有一个名为account_id
的字段和一个名为相同的参数,请将其更改为in_account_id
,并且您的运行时间可以从几秒到百分之一秒。