mysql优化的sql查询比未优化的查询慢?

dw1jzc5e  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(567)

**结束。**此问题需要详细的调试信息。它目前不接受答案。
**想改进这个问题吗?**更新问题,使其成为堆栈溢出的主题。

两年前关门了。
改进这个问题
一位程序员同事向我展示了他创建的一个查询,如下所示:

SELECT a.row, b.row, c.row
FROM 
a LEFT JOIN
b ON (a.id = b.id) LEFT JOIN
c ON (c.otherid= b.otherid)
WHERE a.id NOT IN (SELECT DISTINCT b.id bb 
INNER JOIN
c cc ON (bb.a_id = cc.a_id)
WHERE (bb.date BETWEEN '2018-08-04 00:00:00' AND '2018-08-06 23:59:59'))
GROUP BY a.id ORDER BY c.otherid DESC;

因此,我通过删除第二个查询并直接应用where子句来缩短它:

SELECT a.row, b.row, c.row
FROM 
a LEFT JOIN
b ON (a.id = b.id) LEFT JOIN
c ON (c.otherid= b.otherid)
WHERE b.date NOT BETWEEN '2018-08-04 00:00:00' AND '2018-08-06 23:59:59'
GROUP BY a.id ORDER BY c.otherid DESC;

在此之前,一切似乎都很好,两个查询返回相同的结果集。问题是,第二个查询的执行时间是第一个查询的三倍。这怎么可能?谢谢

v9tzhpje

v9tzhpje1#

这些查询有很大的不同(我们假设失踪者 FROM 在第一个版本中,子查询中的关键字是将其放入问题的结果,并且原始查询没有相同的语法错误。此外,参考 b.idSELECT 子查询的列表非常可疑,我们怀疑它实际上是对 bb.id ... 但我们只是猜测。)
如果两个查询返回相同的精确结果集,则这是数据中的一种情况(我们可以演示两个查询结果不同的数据集。)
“缩短”查询并不一定会优化它。
真正重要的(就绩效而言)是执行计划。也就是说,正在执行哪些操作,以什么顺序执行,对于大型表,哪些索引可用,哪些索引正在使用。
没有表和索引定义,就不可能给出明确的诊断。
建议:使用mysql EXPLAIN 查看每个查询的执行计划。
假设原始查询具有 WHERE 格式条款:

WHERE a.id NOT IN ( SELECT DISTINCT bb.id 
                      FROM b bb 
                      JOIN c cc
                        ON bb.a_id = cc.a_id
                     WHERE bb.date BETWEEN '2018-08-04 00:00:00' 
                                       AND '2018-08-06 23:59:59'
                       AND bb.id IS NOT NULL
                  )

(假设我们保证子查询返回的值永远不会为null…)
可以重写为 NOT EXISTS 关联子查询以获得等效结果:

WHERE NOT EXISTS ( SELECT 1
                       FROM b bb
                       JOIN c cc
                         ON cc.a_id = bb.a_id
                      WHERE bb.date >= '2018-08-04 00:00:00'
                        AND bb.date <  '2018-08-07 00:00:00'
                        AND bb.id = a.id
                   )

或者可以重写为反连接

LEFT 
  JOIN b bb 
    ON bb.id = a.id
   AND bb.date >= '2018-08-04 00:00:00'
   AND bb.date <  '2018-08-07 00:00:00'
  LEFT
  JOIN c cc
    ON cc.a_id = bb.a_id
 WHERE cc.a_id IS NULL

对于大型集合,需要有适当的索引才能获得最佳性能。
问题中的重写不能保证返回相同的结果。

相关问题