MySQL 可直接利用索引滿足 ORDER BY/GROUP BY,避免額外排序(Filesort)。條件:索引列順序與排序列順序一致,且 WHERE 條件覆蓋了索引前綴。
| SQL 模式 | 索引結構 | 說明 |
|---|---|---|
ORDER BY key1, key2 | (key1, key2) | 完全匹配 |
WHERE key1=const ORDER BY key2 | (key1, key2) | WHERE 固定前綴,ORDER BY 緊接其後 |
WHERE key1=const GROUP BY key2 | (key1, key2) | 同理適用 GROUP BY |
ORDER BY key1 DESC, key2 DESC | (key1, key2) | 全降序,MySQL 可逆向掃描索引 |
WHERE key1=1 ORDER BY key1 DESC, key2 DESC | (key1, key2) | 常量條件+全降序 |
| 場景 | 示例 | 原因 |
|---|---|---|
| ORDER BY 列來自不同索引 | ORDER BY key1, key2(key1、key2 非同一複合索引) | 無法合併多索引排序 |
| 非連續索引前綴 | WHERE key2=const ORDER BY key_part2(索引為 key1,key_part2) | WHERE 未覆蓋索引首列 |
| 混合 ASC/DESC | ORDER BY key1 DESC, key2 ASC | 無法單向掃描滿足 |
| WHERE 與 ORDER BY 列不同 | WHERE key2=const ORDER BY key1 | 索引無法同時服務過濾與排序 |
| 多表 JOIN 且排序列非驅動表 | JOIN 查詢,ORDER BY 列不在第一個非 const 表 | 需臨時表合併後排序 |
| ORDER BY 與 GROUP BY 表達式不同 | GROUP BY a ORDER BY b | 需兩次排序 |
| 索引非順序存儲 | HASH、HEAP 表索引 | 底層結構不支持有序掃描 |
EXPLAIN SELECT * FROM t ORDER BY key1, key2;
Extra 列顯示:
Using index:覆蓋索引,無需回表,且已有序。Using filesort:需額外排序,效能隱患。(sort_key, row_ptr) 對。qsort → 寫臨時文件。(sort_key, row_ptr, select_columns) 元組。權衡:元組更大,易超出 sort_buffer_size 導致更多 I/O。受 max_length_for_sort_data 控制:元組總長超過此值才啟用單路排序。
| 參數 | 作用 | 建議 |
|---|---|---|
sort_buffer_size | 排序緩衝區大小(會話級) | 256KB~2MB,避免過大導致內存壓力 |
read_rnd_buffer_size | 隨機讀緩衝(排序後按指針讀行) | 256KB~1MB |
tmpdir | 臨時文件目錄 | 指向高速磁碟,多路徑輪詢分散 I/O |
max_length_for_sort_data | 單路排序觸發閾值 | 1024~4096,觀察磁碟/CPU 負載調整 |
ORDER BY,消除 Filesort。SELECT * 會撐大元組)。sort_buffer_size、read_rnd_buffer_size。tmpdir 指向獨立高速存儲(NVMe/内存盘)。