在資料庫開發中,合理建立索引是提升查詢效能的核心手段之一。特別是針對 ORDER BY 和 GROUP BY 操作,適當的索引設計能避免檔案排序,大幅降低 CPU 和 I/O 開銷。本文系統整理 MySQL 利用索引優化排序的原則、適用場景與常見陷阱,助你寫出高效能 SQL。
MySQL 在單次查詢中只能選擇一個索引。若需對多欄位聯合排序或過濾,必須建立複合索引,且欄位順序需嚴格遵循「最左前綴」原則。
SELECT col1, col2 FROM tbl ORDER BY sort_col;
在 sort_col 上建立單列索引即可利用索引完成排序,避免 filesort。
SELECT col1, col2 FROM tbl WHERE filter_col = 'val' ORDER BY sort_col;
建立複合索引 (filter_col, sort_col)。MySQL 先用索引定位 filter_col,再直接按索引順序讀取 sort_col,實現「where 過濾 + order by 排序」雙重優化。
SELECT * FROM tbl WHERE uid = 1 ORDER BY x, y LIMIT 10;
最佳索引為 (uid, x, y)。注意:索引順序必須與 ORDER BY 欄位順序完全一致,且方向(ASC/DESC)一致。若建立 (x, y, uid) 則無法優化排序。
| 反模式 | 範例 SQL | 原因 |
|---|---|---|
| 對不同索引鍵排序 | ORDER BY key1, key2 (key1、key2 分別建單列索引) |
MySQL 無法合併多個單列索引進行排序 |
| 非連續索引鍵部分排序 | WHERE key2=const ORDER BY key_part2 (聯合索引 key_part1,key_part2) |
跳過索引首欄,導致索引失效 |
| 混合 ASC/DESC | ORDER BY key_part1 DESC, key_part2 ASC |
MySQL 5.7 前不支援混合方向索引掃描 |
| WHERE 與 ORDER BY 非同一索引 | WHERE key2=const ORDER BY key1 |
需建立複合索引 (key2, key1) |
| 排序欄位使用函數/表達式 | ORDER BY YEAR(logindate) |
函數破壞索引順序,必須全表掃描 |
| IN 子查詢導致排序失效 | WHERE col IN (1,2) ORDER BY sort_col |
範圍查詢使後續索引欄位無法用於排序 |
INT 優於 BIGINT,DATE 優於 DATETIME。較小型別減少磁碟、記憶體、CPU 快取佔用。INT UNSIGNED,時間用原生 DATETIME/TIMESTAMP。NULL 會增加索引統計複雜度,建議用 0、空串或特殊值替代,並設 NOT NULL。EXPLAIN 觀察 Extra 欄是否出現 Using filesort,若有則需優化索引。LIMIT offset, N。掌握上述原則,配合 EXPLAIN 持續調優,即可讓 MySQL 排序查詢跑在索引上,實現毫秒級響應。