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

精通 MySQL EXPLAIN:查詢執行計劃深度解析與優化實戰

     編輯:MySQL 資料庫相關知識

前言

EXPLAIN 是 MySQL 查詢優化的核心工具,它揭示了優化器如何執行 SQL 語句。讀懂 EXPLAIN 輸出,等於擁有了「X 光眼」,能精準定位全表掃描、索引失效、臨時表、檔案排序等效能殺手。本文系統整理各欄位含義、連接類型優劣、Extra 關鍵資訊,並提供實戰優化清單。

EXPLAIN 輸出欄位完整解讀

欄位含義關鍵判讀重點
id SELECT 識別符,查詢執行順序標識 id 相同按順序執行;id 越大越優先;NULL 為結果集合併
select_type 查詢類型 SIMPLE 無子查詢/UNION;PRIMARY 最外層;SUBQUERY 子查詢首個 SELECT;DERIVED FROM 子查詢(臨時表);UNION 第二個起;UNION RESULT UNION 結果集
table 當前行存取的表(或衍生表別名) <derivedN> 表示衍生表;<subqueryN> 表示子查詢
partitions 匹配的分區(分區表才顯示) 檢查分區裁剪是否生效
type 核心:存取策略/連接類型,由優到劣 詳見下表「連接類型優劣階梯」
possible_keys 優化器理論上可用的索引 為 NULL 表示無索引可用,需檢查 WHERE/JOIN 條件欄位
key 實際選用的索引 為 NULL 表示無索引;可用 FORCE/USE/IGNORE INDEX 干預
key_len 實際使用的索引長度(位元組) 越短越好(前提不失精度);可推斷複合索引用了幾個欄位
ref 與索引比較的參考值(常數、欄位、函數) const 表示常數比較;func 表示函數/運算式
rows 優化器預估需掃描的行數 越小越好;結合 filtered 估算實際檢索行數
filtered 按表條件過濾後的行百分比 (5.7+) 100 表示無額外過濾;低值意味著大量回表後被丟棄
Extra 關鍵額外資訊,優化重點 詳見下表「Extra 關鍵字含義」

連接類型優劣階梯(由優到劣)

類型說明典型場景效能評級
system表僅有一行(系統表)極少見⭐⭐⭐⭐⭐
const主鍵/唯一索引等值查詢,最多一行匹配WHERE id=1⭐⭐⭐⭐⭐
eq_ref唯一索引/主鍵連接,前表每行匹配後表一行JOIN ON pk = pk⭐⭐⭐⭐
ref非唯一索引等值查詢/連接,前表每行匹配多行WHERE idx_col=val、JOIN ON idx = val⭐⭐⭐
ref_or_null類似 ref,額外搜尋 NULL 值WHERE idx_col=val OR idx_col IS NULL⭐⭐⭐
index_merge索引合併優化(多個索引交集/聯集)WHERE idx1=1 OR idx2=2⭐⭐
range索引範圍掃描(>, <, >=, <=, BETWEEN, IN, LIKE 'prefix%')WHERE id > 100⭐⭐
index全索引掃描(比 ALL 好,因索引通常較小)SELECT 索引覆蓋欄位、ORDER BY 索引欄⭐
ALL全表掃描,最差無索引、索引失效、範圍過大⚠️ 避免

Extra 關鍵字含義與優化對策

Extra 值含義嚴重度優化方向
Using index覆蓋索引,僅讀取索引樹無需回表✅ 極佳維持現狀,適當建立覆蓋索引
Using whereServer 層過濾(存儲引擎返回後再過濾)⚠️ 視情況若 rows 大,嘗試下推條件到索引
Using index conditionICP(Index Condition Pushdown),條件下推到存儲引擎✅ 良好5.6+ 自動開啟,善用複合索引
Using temporary建立臨時表(通常 ORDER BY/GROUP BY 欄位不一致)❌ 差調整索引順序、避免跨表排序、增加 SQL_SMALL_RESULT
Using filesort需額外排序操作(無索引支援 ORDER BY)❌ 差建立符合排序順序的索引、限制結果集大小
Range checked for each record無理想索引,對前表每行重新評估索引選擇❌ 極差建立合適複合索引、重寫查詢
Impossible WHEREWHERE 條件永假,優化器直接返回空結果ℹ️ 提示檢查條件邏輯錯誤
Select tables optimized away聚合查詢直接用索引完成(如 MIN/MAX)✅ 極佳無需優化
Distinct找到第一匹配行後停止掃描✅ 良好配合 LIMIT 1 使用
Not existsLEFT JOIN 優化,找到匹配行後不再搜尋內表✅ 良好正常 LEFT JOIN 行為

實戰優化檢查清單

  1. 鎖定 type 為 ref 以上:出現 ALL、index 必須優化。
  2. 檢查 key 是否為預期索引:若為 NULL 或非預期,用 FORCE INDEX 強制或調整索引結構。
  3. 關注 rows × filtered/100:預估實際處理行數,超過萬行需警惕。
  4. 消除 Using temporary / Using filesort:調整索引順序覆蓋 ORDER BY/GROUP BY。
  5. 追求 Using index(覆蓋索引):SELECT 欄位盡量包含在複合索引中。
  6. 警惕 index_merge:通常意味著缺乏合適複合索引,考慮建立聯合索引替代。
  7. 子查詢優化:DEPENDENT SUBQUERY 往往可改寫為 JOIN 或 EXISTS。
  8. 分區表檢查 partitions:確認分區裁剪生效,避免全分區掃描。

進階技巧

1. 格式化輸出

EXPLAIN FORMAT=JSON SELECT ...;  -- 5.6.5+ 支援,含成本資訊
EXPLAIN FORMAT=TREE SELECT ...;  -- 8.0.16+ 樹狀結構,直觀展示執行順序

2. 配合 ANALYZE 實際執行統計

EXPLAIN ANALYZE SELECT ...;  -- 8.0.18+ 實際執行並顯示耗時、迴圈次數

3. 追蹤優化器決策

SET optimizer_trace="enabled=on";
SELECT ...;
SELECT * FROM information_schema.optimizer_trace;

總結

讀懂 EXPLAIN 是 MySQL 效能調優的入場磚,更是進階必修課。重點記住:type 越靠前越好、key 必須命中、rows 越少越好、Extra 避開 temporary/filesort、追求 Using index。養成「寫 SQL 必跑 EXPLAIN」的習慣,90% 的慢查詢都能在開發階段被攔截解決。

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