Join
多個 Join 中的 SQL Query 流程是怎樣的?
我有一個這樣的查詢:
SELECT * FROM table_1 LEFT JOIN table_2 ON table_1.ID = table_2.ID INNER JOIN table_3 ON table_1.ID = table_3.ID
SQL 如何處理這個連接?SQL 是否連接第一個表 1 和 2。然後將這個新的超級表與表 3 連接起來?或者它會以相反的方式移動?
執行的邏輯順序是您所描述的:
- 它從
FROM
分析它的子句開始:FROM table_1 LEFT JOIN table_2 ON table_1.ID = table_2.ID INNER JOIN table_3 ON table_1.ID = table_3.ID
- 根據優先規則,它變為:
FROM ( table_1 LEFT JOIN table_2 ON table_1.ID = table_2.ID ) INNER JOIN ( table_3 ) ON table_1.ID = table_3.ID
- 所以,是的,它首先(邏輯上)
table_1 LEFT JOIN table_2 ON table_1.ID = table_2.ID
生成一個“超級”表。- 然後它在“超級”表和 table_3 之間進行第二次連接。
- 然後轉到
SELECT
子句,它基本上是按此順序排列的 3 個表的所有列:SELECT table_1.*, table_2.*, table_3.*
- 然後它產生結果集。
但是,實際的執行順序可能完全不同。RDBMS(SQL Server 或 MySQL 或 Postgres 或 Oracle 或 DB2 或……)它允許選擇任何它看起來合適的順序,只要它產生與執行的邏輯順序相同的結果。
- 所以它可以在允許的情況下重新排列連接的順序(這取決於復雜的規則,連接是 LEFT/RIGHT/INNER/FULL,連接條件是任意的還是與 FOREIGN KEY 約束條件相同,連接列是否具有 UNIQUE /PRIMARY 對錶的約束等)
- 不僅是可用的連接順序,還有不同的連接方法(散列、合併、嵌套循環方法等)或使用並行化。
- 它還可以根據查詢中加入的表上的現有索引選擇各種執行路徑。
- 它如何決定選擇哪個執行路徑可能取決於更多細節,例如表和索引的統計資訊、表的大小、列的寬度以及更多優化器/系統設置。
- 它還取決於 RDBMS 和版本。不同的 RDBMS 實現了不同的方法(例如,我認為 MySQL 直到最近才具有雜湊連接,Postgres 僅在 2-3 年前實現了並行查詢,但具有不同類型的廣泛索引,SQL Server 很久以前就具有並行查詢,但有些特性是僅在企業版等),因此選擇的執行路徑可能會因 DBMS 不同而不同,除非是非常簡單的查詢。
SQL 不處理查詢,它是檢查它們的數據庫引擎(MySQL 和 SQL-Server 是其中的兩個)。如今,它解決查詢的方式取決於它認為最便宜的方式,由“優化器”決定,其中包括檢查可用索引和回答查詢所需的數據量。對於要知道的數據量,只要進行了大的更改,就需要對數據進行“分析”。做出這些決定所需的統計資訊無法針對所做的每項更改保持最新,這會損害性能。