2014-05-01 50 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

相關問題