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

MySQL 執行計劃 (EXPLAIN) 深度解析:從入門到調優實戰

     編輯:MySQL 資料庫相關知識

前言

`EXPLAIN` 是 SQL 調優的「聽診器」。看懂執行計劃,等於看懂了 MySQL 如何思考。本文系統講解各列含義、常見類型、優化判斷依據。

測試表結構

CREATE TABLE t1 (
  c1 INT PRIMARY KEY,
  c2 VARCHAR(128), KEY ind_c2(c2),
  c3 VARCHAR(64),
  c4 INT, KEY ind_c4(c4)
) ENGINE=InnoDB;

CREATE TABLE t2 (c1 INT PRIMARY KEY, c2 VARCHAR(128), KEY ind_c2(c2), c3 VARCHAR(64), c4 INT) ENGINE=InnoDB;
CREATE TABLE t3 (c1 INT PRIMARY KEY, c2 VARCHAR(128), KEY ind_c2(c2), c3 VARCHAR(64), c4 INT) ENGINE=InnoDB;

核心列詳細解讀

1. id:查詢序列號

  • **相同**:按順序從上到下執行 (如多表 JOIN)。
  • **不同**:子查詢 id 較大,**id 越大優先級越高,越先執行**。
  • **NULL**:結果合併階段 (如 `UNION RESULT`)。

2. select_type:查詢類型

類型含義
SIMPLE無子查詢/UNION 的簡單查詢
PRIMARY包含子查詢的最外層查詢
SUBQUERYSELECT/WHERE 列表中的子查詢
DERIVEDFROM 列表中的子查詢 (衍生表)
UNIONUNION 中第二個及以後的 SELECT
UNION RESULTUNION 合併結果的虛擬表

3. type:訪問類型 (核心性能指標,由好到壞)

類型含義典型場景性能
system/const常量級訪問,最多 1 行PK/UK 查詢 `WHERE id=1`⭐⭐⭐⭐⭐ 極快
eq_ref唯一索引掃描,JOIN 關聯PK/UK JOIN `ON t1.id=t2.id`⭐⭐⭐⭐ 優
ref非唯一索引掃描普通索引 `WHERE idx_col=val`⭐⭐⭐ 良
range索引範圍掃描`BETWEEN`, `>`, `<`, `IN`, `LIKE 'prefix%'`⭐⭐ 可接受
index全索引掃描覆蓋索引 `SELECT idx_col FROM t`⭐ 較慢
ALL全表掃描無索引、索引失效❌ 差

**目標**:核心查詢至少達到 `ref`,核心 JOIN 達到 `eq_ref`,杜絕 `ALL`。

4. possible_keys / key / key_len

  • `possible_keys`:理論上可用的索引。
  • `key`:**實際使用的索引** (NULL 表示無索引/全表掃描)。
  • `key_len`:索引使用的字節數,**判斷聯合索引用了幾列**:`key_len ≈ 列長度總和` (含 NULL 標誌位)。

5. ref:關聯引用

顯示哪個表的哪個列/常量被用於索引查找。如 `const`、`t1.c1`、`func`。

6. rows:預估掃描行數

基於統計信息估算,**僅供參考**,實際可能相差數量級。關注數量級:10 < 1000 < 100000。

7. Extra:額外信息 (關鍵優化線索)

信息含義優化方向
Using index覆蓋索引,僅掃描索引不回表✅ 極佳,繼續保持
Using whereServer 層過濾 (存儲引擎返回後再過濾)⚠️ 檢查能否下推到引擎 (ICP)
Using index condition (ICP)索引條件下推,引擎層過濾✅ 好,減少回表
Using temporary創建臨時表 (通常 GROUP BY/ORDER BY 異字段)❌ 優化索引/調整 SQL 避免
Using filesort文件排序 (無索引排序/排序字段不匹配)❌ 建立匹配 ORDER BY 的索引
Impossible WHEREWHERE 條件永假✅ 優化器直接返回空
Select tables optimized away聚合查詢優化 (如 MIN/MAX 走索引)✅ 極佳

實戰案例分析

案例 1:全表掃描 → 加索引

EXPLAIN SELECT * FROM t1 WHERE c3 = 'abc';
-- type=ALL, key=NULL, rows=全表行數, Extra=Using where
-- ✅ 優化:ALTER TABLE t1 ADD INDEX idx_c3(c3); → type=ref

案例 2:filesort → 索引排序

EXPLAIN SELECT * FROM t1 WHERE c2='x' ORDER BY c3;
-- type=ref (用 ind_c2), Extra=Using where; Using filesort
-- ✅ 優化:ALTER TABLE t1 ADD INDEX idx_c2_c3(c2, c3); → Extra=Using index condition (無 filesort)

案例 3:覆蓋索引極致優化

EXPLAIN SELECT c1, c2 FROM t1 WHERE c2='x';
-- type=ref, key=ind_c2, Extra=Using index (覆蓋索引,無回表)
-- ✅ 如果 SELECT c1,c2,c3 → 非覆蓋,需回表,考慮加 c3 到索引 (idx_c2_c3) 但權衡寫入開銷

案例 4:聯表 JOIN 優化

EXPLAIN SELECT * FROM t1 JOIN t2 ON t1.c1=t2.c1 WHERE t1.c2='x';
-- t1: type=ref, key=ind_c2
-- t2: type=eq_ref, key=PRIMARY (PK JOIN 最優)
-- ✅ 驅動表 (t1) 有過濾索引,被驅動表 (t2) 用 PK 關聯,完美

調優檢查清單

  1. **type** 是否為 `ALL`/`index`? → 加索引/改寫 SQL。
  2. **key** 是否為 `NULL`? → 無索引可用。
  3. **Extra** 是否有 `Using temporary` / `Using filesort`? → 調整索引順序/方向。
  4. **rows** 是否遠大於返回行數? → 索引選擇性差/條件下推未生效。
  5. **key_len** 是否符合預期聯合索引列數? → 檢查最左前綴是否生效。

總結

讀懂 `EXPLAIN` 核心在於:**看 type 定性能、看 key 定索引、看 Extra 定優化方向**。熟練掌握各列含義,結合業務 SQL 模式,才能精準定位瓶頸、實施有效索引優化。

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