简单的 MySQL 查询需要很长时间来计算

Posted

技术标签:

【中文标题】简单的 MySQL 查询需要很长时间来计算【英文标题】:Simple MySQL queries taking long time to compute 【发布时间】:2011-12-29 05:09:34 【问题描述】:

我刚学 mysql,遇到了一个问题。

有时对于各种查询,MySQL 会在 15-20 秒内以 100% 的 CPU 使用率开始计算,然后它通常会返回结果:

查询耗时 0.1780 秒。

它发生在非常简单的查询上。例如,此查询耗时 0.36 秒。

(SELECT DISTINCT a1.actor 
 FROM   actors AS a1, 
        actors AS a2 
 WHERE  a1.title = a2.title 
        AND a1.YEAR = a2.YEAR 
        AND a1.actor = a2.actor 
        AND a1.character_name <> a2.character_name) 

表(7000 行)的列出耗时 0.001 秒。

另一方面,当我只想将这两者结合起来时,MySQL 发疯了,开始计算 30 秒,然后最终返回:Query took 0.1800 sec)

SELECT actor 
FROM   actors 
WHERE  actor NOT IN (SELECT DISTINCT a1.actor 
                     FROM   actors AS a1, 
                            actors AS a2 
                     WHERE  a1.title = a2.title 
                            AND a1.YEAR = a2.YEAR 
                            AND a1.actor = a2.actor 
                            AND a1.character_name <> a2.character_name) 

为什么会这样?

这是另一个例子。此查询大约需要 2 秒,并报告 0.5

SELECT DISTINCT a1.character_name 
FROM   (actors AS a1 
        NATURAL JOIN movies AS m1), 
       (actors AS a2 
        NATURAL JOIN movies AS m2) 
WHERE  a1.character_name = a2.character_name 
       AND ( m1.title <> m2.title 
              OR ( m1.title = m2.title 
                   AND m1.year <> m2.year ) ) 
       AND m1.country <> m2.country 

另一方面,此查询需要 15-20 秒,CPU 100% 但报告 0.3 秒。 (唯一的区别是 AND ( .... ) 后的括号

SELECT DISTINCT a1.character_name 
FROM   (actors AS a1 
        NATURAL JOIN movies AS m1), 
       (actors AS a2 
        NATURAL JOIN movies AS m2) 
WHERE  a1.character_name = a2.character_name 
       AND m1.title <> m2.title 
        OR ( m1.title = m2.title 
             AND m1.YEAR <> m2.YEAR ) 
           AND m1.country <> m2.country 

我正在使用 phpMyAdmin 和最新的 XAMPP 进行测试。

更新:

错误的查询时间似乎与phpMyAdmin有关,在命令行我得到以下时间:

第一个查询:MySQL:0.36 s - PostgreSQL:0.37 s 第二次查询:MySQL:43 s - PostgreSQL:0.42 s 第三次查询:MySQL:4.86 s - PostgreSQL:0.05 s 第 4 次查询:MySQL:1 分 5 秒 - PostgreSQL:15 秒

所以我知道为什么错误地报告了查询时间(phpMyAdmin 或 XAMPP 中的错误)的答案,我很感兴趣 为什么这样类似的查询在运行时间上有如此大的差异?

更新 2:

为了完整起见,我也使用 PostgreSQL 进行了测试

【问题讨论】:

如果您在WHERE 中粘贴一些内容,它将针对每一行运行,因此其中的嵌套查询将运行 n^2 次。将嵌套查询保留在 FROM 中应该会有很大的不同。 您是否在问为什么它报告的时间与时钟时间不同? 好的,我找到了那部分的答案,这似乎是 phpmyadmin 或 XAAMP 的错误。我感兴趣的是为什么稍微不同的查询会花费如此不同的时间。 确保您将苹果与苹果进行比较。运行查询后,它的计划应该被缓存。因此,如果您在第一次运行查询时查看结果时间,它将与后续运行不同。我相信您的问题不止于此,但请记住一些事情。 我可以同时运行任意次数,它并没有真正改变结果。 【参考方案1】:

您是否尝试过使用 mysql cmd 提示符测试您的查询???如果问题仍然存在,那么问题可能与 mysql 有关,但如果问题得到解决,那么我认为您的 phpmyadmin 有问题。因此,让我知道在尝试使用 mysql cmd 提示符进行查询后,您的问题是否仍然存在。

【讨论】:

感谢您的提示,我重新进行了测试,命令行的值确实可以! 好的,那么我认为问题出在您的 phpmyadmin 上。不知何故,它没有适当地响应。您可以查看此link 和此link。如果这些没有帮助,请尝试全新安装 phpmyadmin 或 xampp(在这种情况下,请保留您的数据库的备份)。【参考方案2】:
SELECT actor 
FROM   actors 
WHERE  actor NOT IN (SELECT DISTINCT a1.actor 
                     FROM   actors AS a1, 
                            actors AS a2 
                     WHERE  a1.title = a2.title 
                            AND a1.YEAR = a2.YEAR 
                            AND a1.actor = a2.actor 
                            AND a1.character_name <> a2.character_name)

上面的查询看起来像是在尝试选择从未在一个标题中扮演过多个角色的演员。你可以说:

select   actor
from     actors
group by actor, year, title
having   count(character_name) = 1

但是,我知道您的问题与您的 sql 编写能力无关,您只是想弄清楚 MySql 出现奇怪行为的原因。我的猜测是它从执行时间中排除了某些事情。例如,当 google 说它需要 0.09 秒才能获得结果时,但您知道您等待 10 秒才能加载页面。 Google 没有考虑从服务器到您的计算机需要 9.91 秒...只是他们查询数据需要多长时间。

这绝对是 MySql 应该解决的一个明显问题,因为不像 Google 不知道等式的另一部分,MySql 应该能够将整个过程纳入时间计算。

【讨论】:

【参考方案3】:

改变这个(你的第一个查询)

SELECT DISTINCT a1.actor 
FROM   actors AS a1, 
actors AS a2 
WHERE  a1.title = a2.title 
AND a1.YEAR = a2.YEAR 
AND a1.actor = a2.actor 
AND a1.character_name <> a2.character_name) 

到这里:

SELECT *
FROM actors a1
JOIN actors a2 ON (a1.title = a2.title AND a1.actor = a2.actor)
GROUP BY a1.actor
HAVING a1.character_name <> a2.character_name

并为其他人使用相同的样式,还要确保您的表格上有正确的索引。

【讨论】:

【参考方案4】:

尝试使用 EXPLAIN 来分析您的查询。我的建议 - 不要使用子查询。

【讨论】:

以上是关于简单的 MySQL 查询需要很长时间来计算的主要内容,如果未能解决你的问题,请参考以下文章

结果集需要很长时间来处理来自 Oracle 的大数据

为啥 SQLite 需要这么长时间来获取数据?

MySQL 服务器上非常简单的 AVG() 聚合查询需要很长时间

如何取消 Java 持久性中正在运行的查询?

避免花很长时间来完成“牛奶过多”的场景

我想减少 MYSQL 查询执行时间。我的查询需要很长时间?