EXPLAIN 分析執行計畫,關注 Using filesort、Using indexSELECT col1, col2 FROM tbl ORDER BY sort_col LIMIT offset, limit;
優化:在 sort_col 建立單欄索引即可避免 filesort。
SELECT col1, col2 FROM tbl WHERE filter_col = 'val' ORDER BY sort_col LIMIT offset, limit;
錯誤做法:分別在 filter_col、sort_col 建單欄索引 → 仍會 filesort。
正確做法:建立聯合索引 (filter_col, sort_col)。
SELECT col1, col2 FROM tbl WHERE filter_col IN ('v1','v2',...) ORDER BY sort_col LIMIT offset, limit;
問題:聯合索引 (filter_col, sort_col) 在 IN 條件下無法直接用於排序,EXPLAIN 顯示 Using where; Using filesort。
嘗試方案:UNION ALL 拆分
(SELECT col1, col2 FROM tbl WHERE filter_col = 'v1' ORDER BY sort_col LIMIT offset, limit)
UNION ALL
(SELECT col1, col2 FROM tbl WHERE filter_col = 'v2' ORDER BY sort_col LIMIT offset, limit)
...
實測結果:往往效能更差(多次掃描、臨時表合併)。實務上強制使用排序索引或應用層分頁效果較好。
-- 錯誤:索引失效
SELECT * FROM tbl ORDER BY YEAR(date_col) LIMIT 30;
-- 正確:範圍查詢可用索引
SELECT * FROM tbl WHERE date_col >= '2024-01-01' AND date_col < '2025-01-01' ORDER BY date_col LIMIT 30;
SELECT * FROM tbl WHERE uid = 1 ORDER BY x, y LIMIT 10;
直覺索引:(x, y, uid) ❌
最佳索引:(uid, x, y) ✅
原因:MySQL 先套用 WHERE 過濾(uid),再依索引順序 (x,y) 輸出,避免 filesort。
| Extra 欄位 | 含義 | 優化方向 |
|---|---|---|
Using filesort | 需額外排序操作(記憶體/磁碟) | 調整索引順序、覆蓋索引 |
Using index | 覆蓋索引,無需回表 | 理想狀態 |
Using where | Server 層過濾 | 正常,若配合 filesort 需優化 |
Using index condition | ICP (Index Condition Pushdown) | 好現象 |
FORCE INDEX 測試指定索引效果?ANALYZE TABLE 更新統計資訊?