2014-10-12 108 views
1

我有兩個提供相同輸出的SQL查詢。 我的第一直覺是使用這樣的:兩個類似SQL查詢之間的巨大性能差異

SELECT * FROM performance_dev.report_golden_results 
where id IN (SELECT max(id) as 'id' from performance_dev.report_golden_results 
group by platform_id, release_id, configuration_id) 

現在,這把像70秒即可完成!

搜索另一種解決辦法我試過類似的東西:

SELECT * FROM performance_dev.report_golden_results e 
join (SELECT max(id) as 'id' 
from performance_dev.report_golden_results 
group by platform_id, release_id, configuration_id) s 
ON s.id = e.id; 

出人意料的是,這場耗時0.05秒即可完成!

這兩個怎麼這麼不同?

謝謝!

+2

'''''''''''''''''''''''這就是爲什麼使用明確的「join」編寫這樣的查詢通常更好。 – 2014-10-12 08:59:30

+0

從我記得,MySql無法正確優化子查詢,但您的第二個查詢使用連接。您需要檢查執行計劃才能正確看到它正在執行的操作 – ydaetskcoR 2014-10-12 09:01:06

+2

查看兩個查詢的'EXPLAIN'輸出。 – Barmar 2014-10-12 09:02:34

回答

0

這可能會導致的時滯第一件事就是MySQL使用「半連接」戰略Subqueries.The半加入,包括以下步驟:

如果一個子查詢符合上述標準時,MySQL將其轉換爲一個 半聯接,使一個基於成本的選擇從這些策略:

轉換子查詢爲連接,或者使用表拉出並運行該查詢 作爲內子查詢表和外表之間的連接。表 拉出從子查詢拉出一個表到外部查詢。

Duplicate Weedout:運行半連接,就好像它是連接一樣,並使用臨時表刪除 重複記錄。 FirstMatch:當掃描行組合的內表和 時,有多個給定值組的實例,選擇一個而不是全部返回它們。這種「快捷方式」掃描並消除了不必要的行的產生。

LooseScan:使用索引掃描子查詢表,該索引可以從每個子查詢的值組中選擇一個 值。

將子查詢物化爲包含索引的臨時表,並使用 臨時表執行連接。該索引用於刪除 重複項。當 將臨時表與外部表連接在一起時,該索引稍後也可用於查找;如果不是,則掃描表 。

但給予明確的加入會減少這些可能是原因的努力。

我希望它有幫助!