EXPLAIN 是 MySQL 性能調優的「核磁共振」,它能展示優化器如何選擇索引、如何連接表、預估掃描行數等關鍵信息。熟練解讀 EXPLAIN 輸出,是每位後端工程師和 DBA 的必備技能。本文系統梳理各列含義、type 等級、Extra 關鍵提示,並給出實戰優化清單。
EXPLAIN SELECT surname, first_name FROM a JOIN b ON a.id = b.id;
MySQL 8.0+ 還支持 EXPLAIN ANALYZE 獲取實際執行耗時、循環次數等運行時統計。
| 列名 | 含義 | 關注重點 |
|---|---|---|
id | 查詢序號,標識 SELECT 子查詢或 UNION 的執行順序 | id 相同按順序執行;id 不同,值大的先執行 |
select_type | 查詢類型:SIMPLE、PRIMARY、SUBQUERY、DERIVED、UNION 等 | 識別複雜查詢結構,DERIVED 往往意味著臨時表 |
table | 當前行訪問的表名或衍生表別名 | 關注是否出現 <derivedN> 或 <subqueryN> |
partitions | 匹配的分區(分區表才顯示) | 檢查分區裁剪是否生效 |
type | 訪問類型,性能由好到差 | 重點列!見下表 |
possible_keys | 優化器理論上可用的索引 | 為 NULL 則無索引可用,需考慮建索引 |
key | 實際選擇的索引 | 為 NULL 表示全表掃描;可用 FORCE INDEX 強制 |
key_len | 索引鍵長度(字節) | 越短越好;可推斷聯合索引用了幾列 |
ref | 與索引比較的列或常量 | const 表示常數等值查詢,極快 |
rows | 預估掃描行數 | 越小越好;若與實際相差大,執行 ANALYZE TABLE |
filtered | 按表條件過濾後剩餘行數百分比 | 越接近 100% 越好 |
Extra | 額外信息,含優化提示 | 重點列!見下文 |
system / const:最多一行,主鍵/唯一索引等值查詢,極快eq_ref:唯一索引/主鍵連接,每張表最多匹配一行ref:非唯一索引等值查詢,可能匹配多行ref_or_null:類似 ref,額外搜索 NULL 值index_merge:索引合併優化,使用多個索引range:索引範圍掃描(>、<、BETWEEN、IN)index:全索引掃描,比全表掃描略快ALL:全表掃描,需優化目標:核心查詢至少達到 range 級別,核心業務力爭 ref 或 eq_ref。
| 提示 | 含義 | 優化方向 |
|---|---|---|
Using index | 覆蓋索引,僅讀索引不回表 | 優秀,繼續保持 |
Using where | Server 層過濾 | 若 rows 大,嘗試下推到引擎層 |
Using temporary | 創建臨時表(常見於 GROUP BY / ORDER BY 不同列) | 調整索引順序、增加覆蓋索引 |
Using filesort | 文件排序,無法利用索引順序 | 優化 ORDER BY 索引、避免跨表排序 |
Range checked for each record | 無好索引,逐行檢查用哪個索引 | 建立更合適的聯合索引 |
Using join buffer | 使用連接緩衝區(Block Nested Loop) | 加被驅動表連接列索引 |
Impossible WHERE | WHERE 條件永假 | 檢查業務邏輯或統計信息 |
ALL:為 WHERE、JOIN、ORDER BY 列建立合適索引Using filesort:索引列順序匹配 ORDER BY,避免 DESC/ASC 混用Using temporary:GROUP BY、ORDER BY 用同一索引;必要時用覆蓋索引Using indexANALYZE TABLE:更新統計信息,讓優化器做出更好決策rows × filtered%:預估實際處理行數,超過萬行需警惕EXPLAIN FORMAT=JSON:輸出結構化 JSON,含 cost_info、used_columns 等更多細節EXPLAIN ANALYZE(8.0.18+):獲取實際執行時間、循環次數、I/O 統計Optimizer Trace 追蹤優化器決策過程key_len:聯合索引 (a,b,c) 查 WHERE a=1 AND c=2 只用 a,key_len 可驗證filtered:rows=10000, filtered=10% 實際只處理 1000 行,不必過度恐慌