掌握LEFT JOIN執行機制與優化策略,是編寫高性能SQL的關鍵。本文深度解析MySQL連接查詢的內部處理流程,並提供實戰優化技巧與最佳實踐案例。
MySQL執行A LEFT JOIN B ON condition時遵循以下步驟:
WHERE B.col IS NULL且col定義為NOT NULL,找到首個匹配行後停止搜索RIGHT JOIN邏輯對稱,僅表角色互換。
優化器自動計算最優連接順序。使用LEFT JOIN或STRAIGHT_JOIN可強制表讀取順序,減少優化器檢查的排列組合,加快優化過程。
-- 低效:強制先讀a,再左連c、d,最後與b關聯導致b全表掃描
SELECT * FROM a, b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key) WHERE b.key=d.key;
-- 優化:調整FROM順序,將b前置
SELECT * FROM b, a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key) WHERE b.key=d.key;
若WHERE條件對NULL行恒為假,MySQL自動將LEFT JOIN轉為內連接:
-- 原查詢:t2.column2=5 對NULL行為假
SELECT * FROM t1 LEFT JOIN t2 ON (t1.column1=t2.column1) WHERE t2.column2=5;
-- 自動優化為:
SELECT * FROM t1, t2 WHERE t2.column2=5 AND t1.column1=t2.column1;
此優化允許優化器優先訪問t2,大幅提升性能。若需強制順序,使用STRAIGHT_JOIN。
大數據多表聯合查詢的黃金法則:
SELECT *)-- 優化寫法:層層過濾,索引命中
SELECT M.*, SS.SensorCode, SS.SensorStatus, ...
FROM (
SELECT T.*, BS.ParkStatus, BS.ChangeTime, CA.CantonName, SE.SectionName
FROM (
SELECT A.*, B.BerthId, B.BerthCode, B.BerthAddress, B.BerthStatus, B.LineDirection, B.CantonId, B.SectionId
FROM (
SELECT AR.AreaId, AR.AreaCode, AR.AreaName
FROM SYS_Area AS AR
WHERE AR.AreaCode='110' -- 核心過濾:最先縮小數據集
) A
LEFT JOIN SYS_Berth AS B ON B.AreaId=A.AreaId
) T
JOIN SYS_BerthStatus AS BS ON T.BerthCode=BS.BerthCode
JOIN SYS_Canton AS CA ON T.CantonId=CA.CantonId
JOIN SYS_Section AS SE ON T.SectionId=SE.SectionId
) M
LEFT JOIN SYS_Sensor SS ON M.BerthCode=SS.BerthCode
LEFT JOIN TRA_PricingBerth AS tp ON tp.BerthCode=M.BerthCode
LEFT JOIN TRA_PricingStrategy AS tps ON tps.PricingStrategyId=tp.PricingStrategyId
LEFT JOIN SYS_BerthAndType AS bat ON bat.BerthCode=M.BerthCode
ORDER BY BerthCode ASC;
關鍵點:最內層WHERE AR.AreaCode='110'優先執行,配合AreaCode索引,極大減少後續JOIN的數據量。
EXPLAIN分析執行計劃,關注type、rows、ExtraSTRAIGHT_JOIN固定連接順序掌握連接查詢優化精髓,讓複雜報表查詢從「分鐘級」進入「毫秒級」。