在聯結與子查詢比較:哪個更快? 文章中,我們了解到聯結往往比子查詢執行得更快。話雖如此,這不是一個通用準則,因此你可能不希望自動假定聯結更為可取。如那篇文章所述,如果你需要在查詢加入許多聯結,資料庫伺服器必須做更多的工作,這可能會導致資料擷取時間變慢。本文將介紹一些你可以執行的快速測試,比較使用聯結的查詢和包含子查詢的查詢,讓你可以選擇效能最好的查詢。
兩個查詢,相同結果
大多數時候,你可以使用聯結或子查詢來編寫查詢。舉例來說,以下是從 MySQL Sakila 範例資料庫中選取地區及其相關城市和地址的查詢。第一個 SELECT 陳述式使用聯結,而第二個 SELECT 陳述式使用子查詢擷取完全相同的資料:
SELECT co.Country, COUNT(DISTINCT ci.city_id) AS city_cnt, COUNT(a.city_id) AS address_cnt FROM country co INNER JOIN city ci ON co.country_id = ci.country_id INNER JOIN address a ON ci.city_id = a.city_id GROUP BY co.country_id; SELECT Co.Country, (Select COUNT(1) FROM City Ci WHERE Ci.country_id=co.country_id) AS city_cnt, (Select COUNT(1) FROM Address A INNER JOIN city c on a.city_id=c.city_id WHERE C.country_id=co.country_id) AS address_cnt From Country Co;
在 Navicat 中,我們可以很容易比較查詢結果,因為它可以同時執行多個查詢。每個結果集都顯示在 SQL 編輯器下方的一個索引標籤中。在下圖中,結果 2 索引標籤的內容顯示在結果 1 旁邊以便快速比較:
查詢執行時間
驗證了這兩個陳述式是對等的之後,我們現在可以比較它們的執行時間。
為此,我們可以選取其中一個陳述式,然後按一下執行按鈕。當在編輯器中選取了文字時,該按鈕的標籤就會變為執行已選取的。在畫面底部可以看到運行時間是 0.020 秒:
對第二個陳述式執行相同的操作,得出運行時間為 0.021秒。時間差別很小,但會隨著資料量的增加而增長:
比較執行計劃
一個查詢的執行計劃可以揭示很多關於它執行速度的資訊。在 Navicat 中,我們可以按一下「解釋」按鈕來檢視執行計劃。雖然需要一些練習才能熟練地解譯解釋的結果,但在嘗試確定查詢的效率時,這樣做是有好處的。
解釋 1 索引標籤顯示第一個(聯結)查詢的執行計劃。我們可以一眼看出它涉及 3 個 SIMPLE 選取:
同時,解釋 2 索引標籤列出了一個 PRIMARY 選取,然後是三個 DEPENDENT SUBQUERY。即使不深入探究,我們也可以看到執行第二個(子查詢)陳述式需要一個額外的步驟:
Conclusion
雖然本文似乎證實了聯結與子查詢比較:哪個更快? 文章得出的結論,但比較聯結和子查詢方法頗有價值的。在任何情況下,子查詢仍然有優勝於聯結的時候,例如當你必須即時計算彙總值並在外部查詢中使用它進行比較時。