首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 5.0 優化系列(二):EXPLAIN 執行計劃全維度解讀與實戰優化案例

     編輯:MySQL 資料庫相關知識

前言

EXPLAIN 是 MySQL 查詢調優的「核磁共振」,能揭示優化器如何執行 SELECT。本文系統講解 輸出字段含義、連接類型層級、Extra 關鍵信息,並通過一個多表 JOIN 實戰案例演示從「全表掃描笛卡爾積」到「索引嵌套循環」的優化全過程。

一、EXPLAIN 兩種用法

-- 1. 表結構別名(等同 DESCRIBE/SHOW COLUMNS)
EXPLAIN tbl_name;

-- 2. 查詢執行計劃(核心用法)
EXPLAIN SELECT select_options ...;

二、輸出字段詳細解讀

字段含義關鍵取值/判讀
idSELECT 標識符同一查詢中遞增;衍生表/子查詢有獨立 id
select_type查詢類型SIMPLE/PRIMARY/UNION/DEPENDENT UNION/SUBQUERY/DEPENDENT SUBQUERY/DERIVED
table引用表別名或 /
type連接類型(性能核心指標)system > const > eq_ref > ref > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
possible_keys可能用到的索引NULL 表示無索引可用 → 檢查 WHERE/JOIN 列
key實際使用的索引NULL 表示未用索引;可用 FORCE/USE/IGNORE INDEX 干預
key_len索引使用長度聯合索引判斷用了幾列;NULL 表未用索引
ref關聯比較值常量/列名/表達式
rows預估掃描行數所有表 rows 乘積 ≈ 總訪問行數;偏大說明統計信息過期
Extra附加信息見下文關鍵值解讀

三、type 連接類型層級詳解(由優到劣)

  1. system:表僅 1 行(系統表特例)
  2. const:主鍵/唯一索引等值查詢,最多 1 行,優化器當常量處理
  3. eq_ref:唯一索引/主鍵所有列參與 JOIN,每張表最多匹配 1 行(最佳 JOIN 類型)
  4. ref:非唯一索引/最左前綴,匹配少量行
  5. ref_or_null:ref + 額外檢查 NULL(子查詢常見)
  6. index_merge:Index Merge 優化(OR 條件多索引合併)
  7. unique_subquery/index_subquery:IN 子查詢轉索引查找
  8. range:索引範圍掃描(=, >, <, BETWEEN, IN)
  9. index:全索引掃描(覆蓋索引時較 ALL 快)
  10. ALL:全表掃描,除非極小表否則需優化

四、Extra 關鍵值紅綠燈

值含義嚴重程度對策
Using filesort需額外排序(無索引服務 ORDER BY)🔴 高調整索引順序/增加排序緩存
Using temporary需創建臨時表(GROUP BY/ORDER BY 列不一致)🔴 高統一排序分組列/增加索引
Using index覆蓋索引(僅讀索引不回表)🟢 優維持/擴展覆蓋索引
Using whereWHERE 過濾(ALL/index 類型下出現需警惕)🟡 中檢查是否可下推索引
Distinct找到首匹配即停止🟢 優-
Not existsLEFT JOIN 優化(滿足即停止)🟢 優-
Range checked...逐行決定索引(無好索引)🟠 中建立更合適索引

五、實戰優化案例:四表 JOIN 從 450 億到 1 萬行掃描

原始查詢

EXPLAIN SELECT tt.TicketNumber, ..., do.CUSTNAME
FROM tt, et, et AS et_1, do
WHERE tt.SubmitTime IS NULL
  AND tt.ActualPC = et.EMPLOYID
  AND tt.AssignedPC = et_1.EMPLOYID
  AND tt.ClientID = do.CUSTNMBR;

初始 EXPLAIN(全 ALL,笛卡爾積)

table  type  possible_keys  key  key_len  ref  rows  Extra
et     ALL   PRIMARY        NULL NULL     NULL 74
do     ALL   PRIMARY        NULL NULL     NULL 2135
et_1   ALL   PRIMARY        NULL NULL     NULL 74
tt     ALL   AssignedPC...  NULL NULL     NULL 3872  range checked...
-- 總掃描行數:74 × 2135 × 74 × 3872 ≈ 4.5×10¹⁰

優化步驟 1:統一字符集長度(CHAR(10) → VARCHAR(15))

ALTER TABLE tt MODIFY ActualPC VARCHAR(15);
-- et.EMPLOYID 已是 CHAR(15)
-- 結果:et 變為 eq_ref,rows 乘積減少 74 倍

優化步驟 2:修正其餘兩個 JOIN 列長度

ALTER TABLE tt MODIFY AssignedPC VARCHAR(15), MODIFY ClientID VARCHAR(15);
-- 結果:et_1、do 均變為 eq_ref,tt 為 ref,僅掃描 52 行

優化步驟 3:更新索引統計信息

ANALYZE TABLE tt;
-- 優化器獲得真實分布,tt 變為 ALL 但僅掃 3872 行(全表),其餘均 eq_ref 1 行
-- 最終總訪問行數 ≈ 3872,性能提升 10⁷ 倍量級

最終 EXPLAIN

table  type   possible_keys  key      key_len  ref            rows  Extra
tt     ALL    AssignedPC...  NULL     NULL     NULL           3872  Using where
et     eq_ref PRIMARY        PRIMARY  15       tt.ActualPC    1
et_1   eq_ref PRIMARY        PRIMARY  15       tt.AssignedPC  1
do     eq_ref PRIMARY        PRIMARY  15       tt.ClientID    1

六、進階技巧

  • STRAIGHT_JOIN:強制按 FROM 順序 JOIN,防優化器誤判
  • ANALYZE TABLE:定期更新統計信息(特別是數據分布變化大的表)
  • rows 乘積估算:粗略評估查詢代價;配合 max_join_size 限制失控查詢
  • 覆蓋索引設計:SELECT 列 ⊆ 索引列 → Extra=Using index

總結

EXPLAIN 不是終點,是起點。讀懂 type、key、rows、Extra 四大核心字段,結合 索引列定義一致性、統計信息鮮度、WHERE/JOIN/ORDER BY 列與索引對齊 三大原則,即可系統性解決 90% 的查詢性能問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved