萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL 外部聯接簡化機制:NULL 拒絕條件與自動轉內部聯接

一、 RIGHT JOIN 統一轉換為 LEFT JOIN

分析階段即將所有 RIGHT JOIN 依規則轉換:

(T1, ...) RIGHT JOIN (T2, ...) ON P(T1,...,T2,...)
= (T2, ...) LEFT JOIN (T1, ...) ON P(T1,...,T2,...)

內部聯接 T1 INNER JOIN T2 ON P 展開為 T1, T2, P 併入 WHERE 或嵌入聯接條件。

二、 優化器搜尋空間限制

含外部聯接查詢時,優化器只考慮「先訪問外表、再訪問內表」的執行計畫,因為 Nested Loop 算法要求外表在外層迴圈。這縮減搜尋空間但可能錯失最佳序。

三、 NULL 拒絕條件 觸發外部聯接簡化

定義

若條件對外部聯接產生的「NULL 補齊行」評估為 FALSE 或 UNKNOWN,則該條件為該外部聯接的 NULL 拒絕條件。

常見 NULL 拒絕條件

  • T2.B IS NOT NULL (內表屬性非空)
  • T2.B > 3, T2.C <= T1.C (含內表屬性的比較)
  • T2.B < 2 OR T2.C > 1 (析取式中任一為 NULL 拒絕)

非 NULL 拒絕條件

  • T2.B IS NULL
  • T1.B < 3 OR T2.B IS NOT NULL (整體對 NULL 行可能為 TRUE)
  • T1.B < 3 OR T2.B > 3

判斷規則總結

  1. 形式為 A IS NOT NULL (A 為內表屬性)。
  2. 含內表引用的判斷式,參量為 NULL 時評估為 UNKNOWN。
  3. NULL 拒絕條件的 OR 聯集。
  4. NULL 拒絕條件的 AND 交集。

四、 逐層轉換與鏈式反應

單一外部聯接轉內部聯接後,可能使上一層外部聯接的條件成為 NULL 拒絕,繼續轉換。

範例:雙層 LEFT JOIN 完全轉為內部聯接

SELECT * FROM T1
LEFT JOIN T2 ON T2.A=T1.A
LEFT JOIN T3 ON T3.B=T2.B
WHERE T3.C > 0;

-- 步驟 1:T3.C>0 對第 2 個 LEFT JOIN 為 NULL 拒絕 → 轉 INNER JOIN
SELECT * FROM T1
LEFT JOIN T2 ON T2.A=T1.A
INNER JOIN T3 ON T3.B=T2.B
WHERE T3.C > 0;

-- 步驟 2:T3.B=T2.B 成為第 1 個 LEFT JOIN 的 NULL 拒絕 → 轉 INNER JOIN
SELECT * FROM T1
INNER JOIN T2 ON T2.A=T1.A
INNER JOIN T3 ON T3.B=T2.B
WHERE T3.C > 0;

最終無外部聯接,優化器可自由排列 T3, T1, T2 等最佳順序。

範例:嵌入式外部聯接僅部分轉換

SELECT * FROM T1
LEFT JOIN (T2 LEFT JOIN T3 ON T3.B=T2.B) ON T2.A=T1.A
WHERE T3.C > 0;

-- 僅內層轉換
SELECT * FROM T1
LEFT JOIN (T2 INNER JOIN T3 ON T3.B=T2.B) ON T2.A=T1.A
WHERE T3.C > 0;

-- 重寫為單層 LEFT JOIN (仍保留外部聯接)
SELECT * FROM T1
LEFT JOIN (T2, T3) ON (T2.A=T1.A AND T3.B=T2.B)
WHERE T3.C > 0;

範例:聯接條件觸發轉換 (WHERE 不拒絕 NULL)

SELECT * FROM T1
LEFT JOIN (T2 LEFT JOIN T3 ON T3.B=T2.B) ON T2.A=T1.A AND T3.C=T1.C
WHERE T3.D > 0 OR T1.D > 0;

-- WHERE 不拒絕 NULL,但 ON 條件 T3.C=T1.C 拒絕 NULL
-- 可將 T3.B=T2.B 提升至 ON
SELECT * FROM T1
LEFT JOIN (T2, T3) ON T2.A=T1.A AND T3.C=T1.C AND T3.B=T2.B
WHERE T3.D > 0 OR T1.D > 0;

五、 ORDER BY 優化補充 (摘要)

  • 索引滿足 ORDER BY 可省略 Filesort。
  • WHERE 常數填補索引前綴缺口可用索引排序。
  • DESC 全部降序同樣可用。
  • Filesort 改進:元組攜帶查詢欄位,避免二次回表;受 max_length_for_sort_data 限制。
  • 調優:增大 sort_buffer_size, read_rnd_buffer_size;tmpdir 指向獨立物理磁碟;GROUP BY 加 ORDER BY NULL 禁用隱含排序。
copyright © 萬盛學電腦網 all rights reserved