EXPLAIN 是 SQL 優化的「聽診器」。本文系統解讀 12 大輸出字段,重點講解 type 訪問類型優劣排序、key_len 推斷聯合索引生效列數、Extra 關鍵提示 (覆蓋索引、臨時表、文件排序) 的判讀與優化動作。
EXPLAIN SELECT * FROM user_info WHERE id = 1;
EXPLAIN SELECT * FROM orders o JOIN user u ON o.uid = u.id WHERE u.status = 1;
| 字段 | 含義 | 優化判讀要點 |
|---|---|---|
id | 查詢序號 | 相同 id 從上到下;id 大優先;衍生表 id 為 NULL |
select_type | 查詢類型 | SIMPLE (無子查詢/UNION)、PRIMARY、SUBQUERY、DERIVED (衍生表/子查詢物化)、UNION/UNION RESULT |
table | 訪問表/衍生表別名 | 確認掃描目標表 |
partitions | 匹配分區 | 分區表檢查裁剪生效 |
type | 訪問類型 (核心!) | 從好到壞:system (表僅1行) > const (主鍵/唯一索引等值) > eq_ref (唯一索引/主鍵 Join) > ref (非唯一索引等值) > fulltext > ref_or_null > index_merge (索引合併) > unique_subquery > index_subquery > range (索引範圍) > index (全索引掃描) > ALL (全表掃描)。目標:至少 ref,避免 ALL/index。 |
possible_keys | 可能用到的索引 | 為空 → 無可用索引,需建立 |
key | 實際使用的索引 | NULL → 未用索引 |
key_len | 索引鍵長度 (字節) | 推斷聯合索引用了幾列: INT=4, BIGINT=8, CHAR(M)=M×字符集字節, VARCHAR(M)=M×字符集字節+2 (長度前綴), NULLABLE+1。 如 INDEX(a,b,c) INT+VARCHAR(20)UTF8+INT,key_len=4+62+4=70 用全列;key_len=4 僅用 a。 |
ref | 與索引比較的值 | const (常量)、列名 (Join 關聯列)、func (函數結果) |
rows | 預估掃描行數 | 越小越好;統計信息過時時偏差大,執行 ANALYZE TABLE |
filtered | 條件過濾後剩餘百分比 | 越高越好;低說明索引選擇性差或條件未下推 |
Extra | 額外信息 (關鍵線索) | 好:Using index (覆蓋索引)、Using where (Server 過濾)。壞: Using filesort (需排序)、Using temporary (臨時表)、Using join buffer (Join Buffer 無索引)、Impossible WHERE (條件永假)、Select tables optimized away (聚合優化)。 |
EXPLAIN SELECT * FROM orders WHERE user_id = 100 AND status = 1;
-- 輸出: type=ref, key=idx_user_status, key_len=9, ref=const,const, rows=12, Extra=Using where
-- 判讀: 聯合索引 (user_id,status) 生效,雙列等值查找,預估 12 行,Server 層再過濾 (Using where 正常)
EXPLAIN SELECT * FROM orders WHERE status = 1 ORDER BY create_time LIMIT 10;
-- 輸出: type=index, key=idx_create_time, rows=1000000, Extra=Using where; Using filesort
-- 判讀: 全索引掃描 (index) + 文件排序,極慢。優化: 建立 idx_status_create_time (status, create_time) 實現 range + 避免排序。
type=ALL → 建立索引、檢查條件列類型匹配、避免函數/運算破壞索引。Using filesort → 調整索引列順序匹配 ORDER BY、MySQL 8.0 使用降序索引 (DESC)。Using temporary → 索引覆蓋 GROUP BY/DISTINCT 列、避免不必要去重。key_len 遠小於索引定義長度 → 聯合索引最左前綴未滿足,調整查詢條件或索引順序。rows 巨大但 LIMIT 很小 → 考慮「延遲關聯」或「游標分頁」。