ORDER BY 是 SQL 查詢中常見的排序操作,其執行效率直接影響查詢效能。本文系統闡述 MySQL 排序的三種執行方式、Filesort 算法演進、JOIN 場景下的排序策略,並給出針對性優化建議。
當 ORDER BY 子句的欄位順序與查詢執行計劃所用索引的索引鍵(或最左前綴)完全一致,且訪問類型為 range、ref 或 index 時,MySQL 可直接按索引順序讀取資料,省去實際排序操作。需注意:
WHERE 已用索引,排序則無法再利用索引;ORDER BY 僅引用第一張表欄位,先對第一張表 Filesort 再聯接;否則需建立臨時表聯接後再排序。測試表 test 擁有聯合唯一索引 u(addtime, a, b):
-- 查詢1:ORDER BY a, b 符合索引最左前綴,Extra 顯示 Using where(無 filesort)
explain select * from test where addtime='2015-10-13 15:38:32' order by a, b;
-- 查詢2:ORDER BY a, b, c 超出索引覆蓋範圍,Extra 顯示 Using filesort
explain select * from test where addtime='2015-10-13 15:38:32' order by a, b, c;
WHERE 與 ORDER BY 使用不同索引;ASC/DESC;WHERE 或 ORDER BY 中對索引欄位使用表達式/函數;WHERE 使用範圍查詢;LEFT JOIN 以右表欄位排序。當無法利用索引排序時,MySQL 在 sort_buffer_size 分配的記憶體中進行排序:
sort_buffer。MySQL 通過比較 max_length_for_sort_data 與查詢欄位總長度決定使用哪種算法:欄位總長度較小時採用單路排序。
Using filesort;Using temporary; Using filesort。關鍵澄清:filesort 並非一定寫磁盤臨時檔,而是「無法用索引排序需實際排序」的代稱;其與磁盤臨時表無直接綁定關係。
Extra 為 NULL;Extra 顯示 Using filesort;Extra 顯示 Using temporary; Using filesort。max_length_for_sort_data:在記憶體充足時提高閾值,誘導 MySQL 選擇單路排序算法,減少隨機 I/O。max_length_for_sort_data 限制,避免因強行增大參數導致分段排序反而降效。sort_buffer_size:減少排序分段與臨時表交換。注意:此為 Connection 級參數,高併發下過大易耗盡記憶體;傳聞超過 2MB 會改用 mmap() 分配記憶體,效率可能下降。