EXPLAIN SELECT * FROM tbl WHERE ...; -- 等同於 DESCRIBE tbl 或 SHOW COLUMNS FROM tbl
關鍵欄位:type (存取類型)、key (實際用索引)、rows (預估掃描行)、Extra (額外資訊)。
只有 ORDER BY 才會觸發 filesort。若 ORDER BY 欄位無索引,無論值是否重複,必現 Using filesort。
SELECT * FROM DB.TB WHERE ID = 2222 AND FID IN (9,8,3,13,38,40) ORDER BY INVERSE_DATE LIMIT 0, 5;
IDX (ID, FID, INVERSE_DATE) -- 三欄複合索引
Using where; Using filesort
複合索引 B+Tree 結構:先按 ID 排序 → 同 ID 下按 FID 排序 → 同 FID 下按 INVERSE_DATE 排序。
查詢條件 ID = 2222 精確匹配第一列,FID IN (...) 為多值匹配 (範圍查詢),導致 INVERSE_DATE 無法保持全局有序,MySQL 必須額外排序 → Using filesort。
-- 新增支援 ORDER BY 的索引 ALTER TABLE DB.TB ADD INDEX idx_id_invdate (ID, INVERSE_DATE);
新索引結構:ID 排序 → 同 ID 下 INVERSE_DATE 排序。查詢時先用 ID=2222 定位,再按索引順序掃描 INVERSE_DATE,直接滿足 ORDER BY,消除 filesort。
| 查詢模式 | 索引設計 | 是否 filesort |
|---|---|---|
| WHERE a=1 ORDER BY b | INDEX (a, b) | 否 |
| WHERE a=1 AND b IN (...) ORDER BY c | INDEX (a, c) 或 (a, b, c) | 視選擇性而定 |
| WHERE a>10 ORDER BY b | INDEX (a, b) | 是 (a 為範圍列) |
| WHERE a=1 ORDER BY b, c | INDEX (a, b, c) | 否 |
>, <, IN, LIKE '%...' 等範圍條件,後續索引列失效SELECT id, name FROM t WHERE id=1 ORDER BY name 若索引含 (id, name) 可避免回表ORDER BY indexed_col LIMIT N 可極大減少排序成本-- 優化前 EXPLAIN SELECT ... ORDER BY INVERSE_DATE LIMIT 5; -- type=ref, Extra=Using where; Using filesort -- 優化後 EXPLAIN SELECT ... ORDER BY INVERSE_DATE LIMIT 5; -- type=ref, Extra=Using where (無 filesort)
現代 MySQL 8.0+ 引入 降序索引 (
INDEX (a ASC, b DESC)) 與 隱藏索引 功能,可更靈活應對混合排序場景。