首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL ORDER BY 索引優化:避免 Filesort 的實戰法則

     編輯:MySQL 資料庫相關知識

核心原則

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/DESCORDER 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:需額外排序,效能隱患。

Filesort 算法演進

MySQL 4.1 前:雙路排序

  1. 讀取符合條件行 → 緩衝區存 (sort_key, row_ptr) 對。
  2. 緩衝區滿 → qsort → 寫臨時文件。
  3. 多路歸併排序臨時文件塊。
  4. 按排序後的 row_ptr 再次讀取數據行(雙次訪問)。

MySQL 4.1+:單路排序

  1. 讀取行 → 緩衝區存 (sort_key, row_ptr, select_columns) 元組。
  2. 按 sort_key 排序元組。
  3. 直接從元組輸出所需列,避免二次讀表。

權衡:元組更大,易超出 sort_buffer_size 導致更多 I/O。受 max_length_for_sort_data 控制:元組總長超過此值才啟用單路排序。

優化 Filesort 的參數調優

參數作用建議
sort_buffer_size排序緩衝區大小(會話級)256KB~2MB,避免過大導致內存壓力
read_rnd_buffer_size隨機讀緩衝(排序後按指針讀行)256KB~1MB
tmpdir臨時文件目錄指向高速磁碟,多路徑輪詢分散 I/O
max_length_for_sort_data單路排序觸發閾值1024~4096,觀察磁碟/CPU 負載調整

終極優化清單

  1. 優先設計索引滿足 ORDER BY,消除 Filesort。
  2. 不可避免 Filesort 時:只選需要的列(SELECT * 會撐大元組)。
  3. 適當增大 sort_buffer_size、read_rnd_buffer_size。
  4. tmpdir 指向獨立高速存儲(NVMe/内存盘)。
  5. 分頁查詢大偏移量時,改用「延遲關聯」或「游標分頁」避免排序海量數據。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved