文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


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

現在,如果先使用資料表 t2 會產生更好的查詢計劃,則最佳化工具可以使用資料表 t2 而不是資料表 t1。若要提供有關資料表聯結順序的提示,請使用最佳化工具提示;請參閱第 10.9.3 節,「最佳化工具提示」。或者,使用 STRAIGHT_JOIN;請參閱第 15.2.13 節,「SELECT 陳述式」。但是,STRAIGHT_JOIN 可能會因為它停用了半聯結轉換而無法使用索引;請參閱使用半聯結轉換最佳化 IN 和 EXISTS 子查詢述詞