EXPLAIN (或 DESCRIBE) 是 SQL 優化的核心工具,揭示優化器的執行計畫。MySQL 5.6+ 新增 EXPLAIN FORMAT=JSON 提供更豐富資訊。
| 欄位 | 核心含義 | 優化關注點 |
|---|---|---|
| id | SELECT 識別符,序號 | 同 id 由上而下執行;衍生表/子查詢 id 較大 |
| select_type | 查詢類型 | SIMPLE/PRIMARY/UNION/SUBQUERY/DERIVED/DEPENDENT... |
| table | 存取的表 (含衍生表 | 關注存取順序 |
| type (關鍵) | 存取類型/聯接策略 | system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL 目標:至少 range,最佳 ref/eq_ref/const |
| possible_keys | 可能用到的索引 | 為 NULL 表示無索引可用,檢查 WHERE/JOIN/ORDER BY 欄位 |
| key | 實際使用的索引 | 為 NULL 表示全掃;可用 FORCE/USE/IGNORE INDEX 干預 |
| key_len | 實際使用的索引長度 | 推斷聯合索引用了幾個欄位 (含 NULL 標誌位 1 byte) |
| ref | 與 key 配合的比較值 | const/欄位名/函數表達式 |
| rows (關鍵) | 預估掃描行數 | InnoDB 為估算值;乘積過大 (> 10^6) 需優化 |
| Extra (關鍵) | 額外資訊 | Using index (覆蓋索引) / Using where / Using temporary / Using filesort (需優化) / Impossible WHERE |
system/const:單行查詢,極快 (主鍵/唯一鍵等值查找)。eq_ref:主鍵/唯一鍵聯接,每行最多一匹配,最佳聯接。ref:非唯一索引等值查找/聯接,匹配行較少時可接受。range:索引範圍掃描 (>, >=, <, <=, BETWEEN, IN)。index:全索引掃描 (覆蓋索引時優於 ALL)。ALL:全表掃描,大表禁忌。| Extra 值 | 含義 | 對策 |
|---|---|---|
| Using filesort | 需額外排序 (記憶體/磁碟) | 加索引支援 ORDER BY;避免 WHERE 與 ORDER BY 索引衝突 |
| Using temporary | 建立臨時表 (GROUP BY/DISTINCT/UNION) | 優化索引順序;小結果集可接受 |
| Using index | 覆蓋索引,僅讀索引樹 | 優化目標,盡量達成 |
| Range checked for each record | 無合適索引,逐行嘗試 | 建立合適聯合索引 |
-- 原始:4 表 ALL 掃描,rows 乘積 452 億
EXPLAIN SELECT ... FROM tt, et, et AS et_1, do WHERE ...;
-- 步驟 1:修正欄位長度不一致 (tt.actualpc char(10) vs et.employid char(15))
ALTER TABLE tt MODIFY actualpc VARCHAR(15), MODIFY assignedpc VARCHAR(15), MODIFY clientid VARCHAR(15);
-- rows 乘積降 74 倍
-- 步驟 2:ANALYZE TABLE 更新統計資訊
ANALYZE TABLE tt;
-- 最終計畫:tt ALL (驅動表) → et/et_1/do eq_ref (主鍵查找)
-- 執行時間從分鐘級降至 2 秒內
STRAIGHT_JOIN 強制聯接順序 (慎用,優化器通常更聰明)。EXPLAIN ANALYZE (MySQL 8.0.18+) 顯示實際執行時間與行數,對比預估值。filtered 欄位 (Extended 模式),低於 10% 表示 WHERE 過濾率極低,需加索引。