CREATE TABLE A(c1 INT PRIMARY KEY, c2 CHAR(2), c3 VARCHAR(16), c4 DATETIME) ENGINE=MyISAM;
CREATE TABLE B(c1 INT PRIMARY KEY, c2 CHAR(2), c3 VARCHAR(16), 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;
執行計劃:type=range, key=PRIMARY, Extra=Using where(無 Filesort)
原理:ORDER BY A.c1 與主鍵索引順序一致,按索引掃描天然有序。
流程圖:
索引掃描 (PRIMARY) → 滿足 WHERE → 直接輸出有序結果
EXPLAIN SELECT A.* FROM A,B
WHERE A.c1 > 2 AND A.c2 < 5 AND A.c2 = B.c2
ORDER BY A.c2;
執行計劃:Extra=Using where; Using filesort
流程圖:
索引/全表掃描 → 滿足 WHERE → 收集 (sort_key, row_ptr) → sort_buffer 排序 → 輸出
EXPLAIN SELECT A.* FROM A,B
WHERE A.c1 > 2 AND A.c2 < 5 AND A.c2 = B.c2
ORDER BY B.c3;
執行計劃:Extra=Using where; Using temporary; Using filesort
原因:ORDER BY 列來自非驅動表,MySQL 必須先構建臨時表存放 JOIN 結果,再排序。
流程圖:
JOIN 執行 → 寫入臨時表 → Filesort 臨時表 → 輸出
| 特性 | 雙值排序 (≤4.0) | 元組排序 (4.1+) |
|---|---|---|
| 存儲內容 | (sort_key, row_ptr) | (sort_key, row_ptr, select_columns) |
| 回表次數 | 2 次 | 1 次 |
| sort_buffer 佔用 | 小 | 大 |
| 觸發條件 | SELECT 列總長 > max_length_for_sort_data | SELECT 列總長 ≤ max_length_for_sort_data |
max_length_for_sort_datasort_buffer_sizeUsing filesort 即需優化(where_col, order_col) 聯合索引