有人可以解释为什么通过子查询添加组会使此查询花费这么长时间(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)
如果我删除'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)
子查询中没有外部引用,所以它只应执行一次,对吧?自己执行:
SELECT sources.musical_work_id FROM sources GROUP BY sources.musical_work_id HAVING COUNT(sources.musical_work_id) > 8
只需0.01秒。
有任何解释吗?有关如何更改它的任何建议吗?
答案 0 :(得分:6)
子查询中没有外部引用,所以它只应执行一次,对吧?
你会这么认为,但不是。如果查看EXPLAIN,您将看到子查询被称为“依赖子查询”而不是“子查询”。这意味着每次都会重新执行。这是MySQL 5.0中的known bug,并在MySQL 6.0中修复。
要解决此问题,您可以使用其他方法之一来检查另一个表中是否存在行。三个常用方法是NOT IN,NOT EXISTS和LEFT JOIN ... WHERE ... IS NULL,所以你还有两个选项。
答案 1 :(得分:2)
NOT IN可能是你的问题。尝试加入它(你必须翻转HAVING子句):
SELECT *
FROM aggregate_songlist AS a
INNER JOIN musical_works AS m
ON a.musical_work_id = m.id
LEFT JOIN (
SELECT sources.musical_work_id FROM sources
GROUP BY sources.musical_work_id
HAVING COUNT(sources.musical_work_id) <= 8) AS t
ON m.id = t.musical_work_id
WHERE m.genre='rock' AND t IS NULL
[更新以反映@Mark Byers的评论,谢谢!]
答案 2 :(得分:0)
SELECT *
FROM
aggregate_songlist AS a
INNER JOIN musical_works AS m
ON a.musical_work_id = m.id
LEFT JOIN (
SELECT sources.musical_work_id FROM sources
GROUP BY sources.musical_work_id
HAVING COUNT(sources.musical_work_id) <= 8)
AS t
ON m.id = t.musical_work_id
WHERE
m.genre='rock' AND
t.musical_work_id IS NULL