我该如何优化这个MySQL查询?

use*_*736 4 mysql sql

有人可以解释为什么子查询添加组使得此查询需要这么长时间(30秒):

SELECT *
FROM aggregate_songlist AS a
INNER JOIN musical_works AS m 
ON a.musical_work_id = m.id
WHERE m.genre='rock' AND m.id NOT IN 
(SELECT sources.musical_work_id FROM sources GROUP BY sources.musical_work_id HAVING COUNT(sources.musical_work_id) > 8)
Run Code Online (Sandbox Code Playgroud)

如果我删除'group by'(并增加子查询的结果),则需要0.07秒:

SELECT *
FROM aggregate_songlist AS a
INNER JOIN musical_works AS m 
ON a.musical_work_id = m.id
WHERE m.genre='rock' AND m.id NOT IN 
(SELECT sources.musical_work_id FROM sources)
Run Code Online (Sandbox Code Playgroud)

子查询中没有外部引用,因此它只应执行一次,对吧?自己执行:

SELECT sources.musical_work_id FROM sources GROUP BY sources.musical_work_id HAVING COUNT(sources.musical_work_id) > 8
Run Code Online (Sandbox Code Playgroud)

只需0.01秒.

有什么解释吗?有关如何改变它的任何建议?

Mar*_*ers 6

子查询中没有外部引用,因此它只应执行一次,对吧?

你会这么认为,但不是.如果查看EXPLAIN,您将看到子查询被称为"依赖子查询"而不是"子查询".这意味着每次都会重新执行.这是MySQL 5.0中的一个已知错误,并在MySQL 6.0中修复.

要解决此问题,您可以使用其他方法之一来检查另一个表中是否存在行.三种常用方法是NOT IN,NOT EXISTS和LEFT JOIN ... WHERE ... IS NULL,所以你仍然有两个选项.