在 MySQL 中,ORDER BY 子句的執行效能直接影響查詢回應速度。MySQL 採用兩種截然不同的排序實現方式:一種是借助有序索引直接獲取已排序的資料,另一種則是在記憶體中透過排序演算法對結果集進行排序(即 filesort)。理解這兩種機制的觸發條件與優劣差異,是 SQL 調優的關鍵環節。
當 ORDER BY 的排序欄位與執行計劃所使用的索引鍵(或聯合索引的最左前綴)完全一致,且索引訪問類型為 range、ref 或 index 時,MySQL 可直接按索引順序讀取資料,完全省略排序操作。這是效能最優的場景。
假設有兩張表 A(主鍵 c1)與 B(主鍵 c1,索引 c2):
CREATE TABLE `A` (`c1` int(11) NOT NULL default '0', `c2` char(2) default NULL, `c3` varchar(16) default NULL, `c4` datetime default NULL, PRIMARY KEY (`c1`)) ENGINE=MyISAM;
CREATE TABLE `B` (`c1` int(11) NOT NULL default '0', `c2` char(2) default NULL, `c3` varchar(16) default NULL, PRIMARY KEY (`c1`), KEY `B_c2_ind` (`c2`)) ENGINE=MyISAM;
執行查詢:
EXPLAIN SELECT A.* FROM A,B WHERE A.c1 > 2 AND A.c2 < 5 AND A.c2 = B.c2 ORDER BY A.c1;
執行計劃顯示表 A 的 type=range、key=PRIMARY,且 Extra 欄沒有 Using filesort。這意味著 MySQL 直接掃描主鍵索引,按 c1 遞增順序輸出結果,流程如下圖:

當無法利用索引順序時,MySQL 必須在 sort_buffer_size 分配的記憶體區域(每個線程獨享)中進行排序,執行計劃會顯示 Using filesort。MySQL 4.1 之前僅支援「單路排序」(Two-pass),4.1 引入「雙路排序」(Single-pass)以減少 I/O。
| 演算法 | 流程 | 優點 | 缺點 | 適用條件 |
|---|---|---|---|---|
| 單路排序 (Two-pass) | 1. 讀取符合條件的行指針與排序欄位 2. 在 sort_buffer 排序 3. 再次按指針回表讀取所需欄位 | 佔用 sort_buffer 空間小 | 需兩次訪問資料表,I/O 成本高 | 欄位總長度 > max_length_for_sort_data |
| 雙路排序 (Single-pass) | 1. 一次性讀取所有需輸出的欄位 2. 在 sort_buffer 直接排序 3. 直接輸出結果 | 僅一次 I/O,速度快 | 佔用大量 sort_buffer,易導致磁臨時檔 | 欄位總長度 ≤ max_length_for_sort_data |
調優建議:若系統出現大量 Sort_merge_passes 或排序等待,可適當增大 max_length_for_sort_data(預設 1024 bytes)強制使用雙路排序,並配合增大 sort_buffer_size,可顯著降低 CPU 與 I/O 壓力。
將上述查詢改為 ORDER BY A.c2,因 A.c2 無索引,執行計劃出現 Using filesort:
EXPLAIN SELECT A.* FROM A,B WHERE A.c1 > 2 AND A.c2 < 5 AND A.c2 = B.c2 ORDER BY A.c2;
MySQL 先按主鍵範圍掃描表 A 取得符合條件的行,再在記憶體中按 c2 排序,流程如下:

MySQL 要求 filesort 的資料來源必須來自單一表。若 ORDER BY 欄位屬於非驅動表(如 ORDER BY B.c3),MySQL 必須先建立內部臨時表,將 JOIN 結果物化,再對臨時表排序。執行計劃會同時出現 Using temporary 與 Using filesort,效能開銷極大:
EXPLAIN SELECT A.* FROM A,B WHERE A.c1 > 2 AND A.c2 < 5 AND A.c2 = B.c2 ORDER BY B.c3;

ORDER BY 欄位匹配聯合索引最左前綴,避免 filesort。max_length_for_sort_data 與 sort_buffer_size,平衡記憶體佔用與 I/O 次數。EXPLAIN:重點關注 Extra 欄的 Using filesort、Using temporary 標識,定位效能瓶頸。掌握 MySQL 兩大排序機制的內部原理,能幫助開發者從索引設計、參數調優、SQL 改寫三個維度徹底解決排序效能問題。