文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 39.9Mb
PDF (A4) - 40.0Mb
手冊頁 (TGZ) - 258.5Kb
手冊頁 (Zip) - 365.5Kb
資訊 (Gzip) - 4.0Mb
資訊 (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  外部聯結最佳化

10.2.1.9 外部聯結最佳化

外部聯結包含 LEFT JOINRIGHT JOIN

MySQL 實作 A LEFT JOIN B join_specification 如下

  • 將資料表 B 設定為依賴資料表 A 以及 A 依賴的所有資料表。

  • 將資料表 A 設定為依賴 LEFT JOIN 條件中使用的所有資料表(除了 B 之外)。

  • LEFT JOIN 條件會用來決定如何從資料表 B 擷取資料列。(換句話說,不會使用 WHERE 子句中的任何條件。)

  • 會執行所有標準聯結最佳化,但資料表一定會在依賴的所有資料表之後讀取除外。如果有循環依賴,就會發生錯誤。

  • 會執行所有標準 WHERE 最佳化。

  • 如果 A 中有一個符合 WHERE 子句的資料列,但 B 中沒有符合 ON 條件的資料列,就會產生一個額外的 B 資料列,其中所有資料行都設定為 NULL

  • 如果您使用 LEFT JOIN 來尋找某些資料表中不存在的資料列,且 WHERE 部分有下列測試:col_name IS NULL,其中 col_name 是宣告為 NOT NULL 的資料行,MySQL 會在找到一個符合 LEFT JOIN 條件的資料列之後,停止搜尋更多資料列(針對特定的索引鍵組合)。

RIGHT JOIN 的實作類似於 LEFT JOIN,只是資料表角色反轉。右聯結會轉換為對等的左聯結,如第 10.2.1.10 節,「外部聯結簡化」中所述。

對於 LEFT JOIN,如果產生的 NULL 資料列的 WHERE 條件始終為 false,LEFT JOIN 會變更為內部聯結。例如,如果 t2.column1NULL,則下列查詢中的 WHERE 子句會為 false

SELECT * FROM t1 LEFT JOIN t2 ON (column1) WHERE t2.column2=5;

因此,將查詢轉換為內部聯結是安全的

SELECT * FROM t1, t2 WHERE t2.column2=5 AND t1.column1=t2.column1;

在準備階段,會移除由常數文字表達式產生的無意義 WHERE 條件,而不是在稍後的優化階段才移除,屆時聯結已經簡化。提早移除無意義條件可讓優化器將外部聯結轉換為內部聯結;這可以改善在 WHERE 子句中包含無意義條件的外部聯結查詢的計畫,例如這個查詢。

SELECT * FROM t1 LEFT JOIN t2 ON condition_1 WHERE condition_2 OR 0 = 1

現在,優化器在準備階段會看到 0 = 1 永遠為 false,因此 OR 0 = 1 是多餘的,並將其移除,剩下這個:

SELECT * FROM t1 LEFT JOIN t2 ON condition_1 where condition_2

現在,優化器可以將查詢重寫為內部聯結,如下所示:

SELECT * FROM t1 JOIN t2 WHERE condition_1 AND condition_2

現在,如果這樣做可以產生更好的查詢計畫,則優化器可以在表 t1 之前使用表 t2。若要提供有關表聯結順序的提示,請使用優化器提示;請參閱第 10.9.3 節「優化器提示」。或者,使用 STRAIGHT_JOIN;請參閱第 15.2.13 節「SELECT 陳述式」。但是,STRAIGHT_JOIN 可能會因為禁用半聯結轉換而導致無法使用索引;請參閱使用半聯結轉換優化 IN 和 EXISTS 子查詢謂詞