Join

多個 Join 中的 SQL Query 流程是怎樣的?

  • January 7, 2022

我有一個這樣的查詢:

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 是其中的兩個)。如今,它解決查詢的方式取決於它認為最便宜的方式,由“優化器”決定,其中包括檢查可用索引和回答查詢所需的數據量。對於要知道的數據量,只要進行了大的更改,就需要對數據進行“分析”。做出這些決定所需的統計資訊無法針對所做的每項更改保持最新,這會損害性能。

引用自:https://dba.stackexchange.com/questions/305761