【问题标题】:Why is this MySQL query so slow?为什么这个 MySQL 查询这么慢?
【发布时间】:2013-12-02 16:39:33
【问题描述】:

我们正在努力让这个查询在可以容忍的时间内运行:

SELECT `User`.`id`,
FROM `users` AS `User` 
LEFT JOIN `attempts` AS `Attempt` ON (`Attempt`.`user_id` = `User`.`id` AND `Attempt`.`test_id` != 875) 
LEFT JOIN `resumes` AS `Resume` ON (`Resume`.`user_id` = `User`.`id`) 
WHERE `Attempt`.`test_id` = 964 AND `Attempt`.`score` > 10 AND `Resume`.`has_file` = 1 AND `Resume`.`user_id` = `User`.`id` 

总共大约有 50,000 个用户行。

LIMIT 为 1000 或更少时,查询几乎是即时的。但如果限制不存在,它会在 300 秒后超时(我们的测试环境允许的最大值)。

我们需要能够在 10 秒或更短的时间内从查询中返回所有结果。有时这将是大约 10,000 条记录。这不现实吗?或者我们是否在做一些次优的事情,导致这个查询如此缓慢。

如果相关,当我从命令行(不是通过我的 PHP 应用程序)运行此查询时,它非常快,即使返回 10K 记录也是如此。

*更新:* EXPLAIN 表明索引没有被用于连接的表之一

【问题讨论】:

  • 尝试运行 EXPLAIN 看看它是否使用了正确的索引
  • 为什么客户端需要 10,000 行?您不想分页数据吗?
  • 这不是您的问题。此外,您的 WHERE 条件将所有 OUTER JOINS 都呈现为 INNER JOINS,因此您不妨一开始就以这种方式编写它们。
  • 这看起来很像这个问题并且遇到类似的问题:stackoverflow.com/questions/20248803/…
  • 你应该放弃 ` AND Attempt.test_id != 875 ` 因为你已经有了一个限制性的 WHERE 子句并且你也不需要AND Resume.user_id` = @ 987654329@.id ` 在 WHERE 子句中,因为它在连接中(或者,使连接成为 INNER JOIN)

标签: mysql sql join


【解决方案1】:

您的 JOINWHERE 子句非常混乱,就像我上面评论中提到的问题一样。

试试这个:

SELECT `User`.`id`
FROM `users` AS `User` 
INNER JOIN `attempts` AS `Attempt` ON `Attempt`.`user_id` = `User`.`id` 
INNER JOIN `resumes` AS `Resume` ON `Resume`.`user_id` = `User`.`id`
WHERE `Attempt`.`test_id` = 964 
    AND `Attempt`.`score` > 10 
    AND `Resume`.`has_file` = 1 

【讨论】:

    【解决方案2】:

    即使你有好的索引,你也应该避免这样的标准:

    `Attempt`.`test_id` != 875
    `Attempt`.`score` > 10
    

    并用 IN() 或类似的东西替换它们

    `Attempt`.`test_id` = 964
    

    【讨论】:

    • 您确定IN() 更快吗?我被教导要尽可能避免子查询。
    • 我的意思是 IN(id1, id2, id3...) 不是 IN(SELECT ...)
    猜你喜欢
    • 2011-03-11
    • 2012-06-13
    • 1970-01-01
    • 2020-03-19
    • 2014-03-12
    • 2011-02-28
    • 1970-01-01
    • 1970-01-01
    • 2017-10-12
    相关资源
    最近更新 更多