2012-09-11 42 views
1

考慮2個MySQL查詢:簡單的MySQL的子查詢性能

SELECT ue.userid,e.courseid 
FROM (SELECT id,courseid FROM mdl_enrol WHERE status = 0 AND courseid IN (46)) e 
INNER JOIN (SELECT enrolid,userid FROM mdl_user_enrolments) ue ON ue.enrolid = e.id 
INNER JOIN (SELECT userid FROM mdl_userdata) ud ON ue.userid = ud.userid 

-

SELECT ue.userid,e.courseid 
FROM mdl_enrol e 
INNER JOIN mdl_user_enrolments ue ON ue.enrolid = e.id 
INNER JOIN mdl_userdata ud ON ue.userid = ud.userid 
WHERE e.status = 0 AND e.courseid IN (46) 

底部查詢是很多很多比上查詢速度快,但爲什麼呢?我已經讀過,爲了提高性能,您只應選擇所需的列。此外,對我來說,頂級查詢應該會更好,因爲在每個JOIN中,您都會減少要加入的數據量。很明顯,我對數據庫的工作原理的理解是錯誤的,但如果有人能夠清楚這一點,將會非常感激。 EXPLAIN也證實底部查詢速度更快。

非常感謝。

+0

「提高性能,你應該只選擇你需要的列」---並提高性能,你應該避免使用子查詢:-) – zerkms

回答

2

在第一個查詢的MySQL應該從mdl_enrol表和完整mdl_user_enrolmentsmdl_userdata到內存中選擇一個子集。所以你在內存中選擇了很多數據。完成之後 - 你加入數據。如果沒有足夠的內存來存儲所有數據,直到它們被加入併發送回客戶端 - 那麼將創建硬盤上的臨時表。很可能,mysql優化器不夠酷,無法解決您的錯誤,並嘗試改進執行計劃。這就是爲什麼它很慢。

對於第二個查詢,mysql知道它究竟需要選擇什麼,只選擇少量所需的數據。在這種情況下,可以使用索引(假設所有必要的索引已經創建)。所以它很快。

+0

感謝您的迴應。所以基本上如果你避免子查詢,MySQL不太可能需要創建臨時表(一旦內存已滿)。而且,在使用子查詢時,索引效率較低,或者根本沒有效果? – paul78

+0

@ paul78:有一些近似 - 是的。查詢優化過程非常困難,但避免子查詢是一個很好的經驗法則。雖然有子查詢的有效情況 - 但它是另一個故事;-) – zerkms