2014-05-01 45 views
0

考虑以下查询:为什么加入子查询非常慢?

SELECT 
    ... 
FROM table1 
LEFT JOIN table2 ... 
LEFT JOIN table3 ... 
LEFT JOIN table4 ... 
LEFT JOIN table5 ... 
LEFT JOIN 
(
SELECT id, COUNT(*) as qty FROM other WHERE ... GROUP BY id 
) temp ON temp.id = table1.id 
WHERE temp.qty = 123 
GROUP BY table1.id 

此查询速度很慢,但是当我执行

SELECT id, COUNT(*) as qty FROM other WHERE ... GROUP BY id 
单独

,它的速度极快,它返回只有少数(20-30)行...

我目前的解决方案是与索引临时表,我写些数据,然后我用加入:

DROP TABLE IF EXISTS tmp_counts; 
CREATE TABLE tmp_counts id INT(11), qty INT(11) ... 
INSERT INTO tmp_counts (id,qty) (SELECT id, COUNT(*) as qty FROM other WHERE ... GROUP BY id); 
SELECT 
    ... 
FROM table1 
LEFT JOIN table2 ... 
LEFT JOIN table3 ... 
LEFT JOIN table4 ... 
LEFT JOIN table5 ... 
LEFT JOIN tmp_counts ON tmp_counts.id = table1.id 
WHERE tmp_counts.qty = 123 
GROUP BY table1.id 

它工作得非常快,但我觉得这是一个丑陋的解决方案。

MySQL真的很愚蠢我需要自己动手做mysql作业吗?

+1

你看过执行计划吗? – Brandon

+0

@Brandon它正确地使用索引,子查询被标记为派生的,临时表使用其中 – Peter

回答

3

MySQL不是很蠢。优化数据库非常复杂。事实上,当你考虑这个问题时,很少有软件可以在如此多种不同的情况下进行这种优化。程序和面向对象的语言 - 他们被告知该怎么做。在SQL中,我们说我们想要的,并让优化器找出最好的。反过来说,什么最好可以严重依赖于基础数据。

有时候优化器是错误的。有时我们可以说服它。这里的问题很可能是连接顺序或连接算法的选择。一种方法来解决这样的问题是在select相关子查询来替换子查询:

选择

SELECT . . ., 
     (SELECT COUNT(*) 
     FROM other 
     WHERE . . . AND 
       other.id = table1.id 
     ) as qty 
    ... 
FROM table1 
LEFT JOIN table2 ... 
LEFT JOIN table3 ... 
LEFT JOIN table4 ... 
LEFT JOIN table5 ... 
GROUP BY table1.id; 

这,反过来,还可以通过对other创建索引优化。至少,这将是other.id

+0

感谢您的答案,可能您是对的,我想从优化器太多,我会坚持使用当前的解决方案,毕竟它不是那么糟糕。 ..而我真正的查询更复杂,我不能使用您的答案查询,因为它会更慢 – Peter

+0

@Peter。 。 。你怎么知道没有尝试它会更慢? –

+0

我刚试过,我必须承认它比我原来的查询更快,但仍然比临时表慢。 (也许是因为我的子查询产生很少的行?)。现在我需要考虑选择什么,因为也许将来我的子查询可能会产生更多的行... – Peter

相关问题