MySQL 8.0+中通过EXPLAIN FORMAT=json查看filesort_information下的sort_mode值:"<sort_key, additional_fields>"或"<sort_key, packed_additional_fields>"为单路排序,"<sort_key, rowid>"为双路排序;该判断基于max_length_for_sort_data与SELECT字段总长度的比较,而非数据量大小。

EXPLAIN FORMAT=json 里看 sort_mode
MySQL 8.0+ 最直接的方式是用 EXPLAIN FORMAT=json 查执行计划,关键字段在 "filesort_information" 下的 sort_mode 值:
-
"<sort_key additional_fields>"</sort_key>或"<sort_key packed_additional_fields>"</sort_key>→ 单路排序 -
"<sort_key rowid>"</sort_key>→ 双路排序
注意:不是所有版本都支持 FORMAT=json;5.7 及更早需用 optimizer trace。另外,rowid 在 InnoDB 中实际是主键值(聚簇索引键),不是物理行号。
optimizer trace 中搜 sort_mode
所有 MySQL 版本通用,但需手动开启并查结果:
- 执行前先开 trace:
SET optimizer_trace="enabled=on"; - 跑你的
SELECT ... ORDER BY查询 - 查
SELECT * FROM information_schema.optimizer_trace\G - 在输出 JSON 中搜索
sort_mode字段,值同上
别漏掉 "mismatch_reason": "..." 字段——它可能告诉你为什么没走索引排序而 fallback 到 filesort,比如 Using temporary; Using filesort 出现在 Extra 里时,就说明一定触发了单路或双路。
为什么 max_length_for_sort_data 是关键阈值
MySQL 内部用这个变量(默认 1024 字节)和「查询涉及的所有非排序列总长度」做比较,决定走哪条路:
- 若
sum(列字节长度) ≤ max_length_for_sort_data→ 优先单路 - 若含
TEXT、BLOB或宽VARCHAR,哪怕只一列,也大概率触发双路 - 调小该值(如设为 512)可强制更多查询走双路,减少 sort_buffer 压力;调大(如 4096)可能让小表查询更倾向单路,但要小心内存溢出写磁盘
这个判断发生在优化器阶段,不依赖数据量大小,只看字段定义和 SELECT 列表 —— 所以即使 LIMIT 1,只要选了 3 个 VARCHAR(500),也可能双路。
容易被忽略的陷阱:sort_buffer_size 不够时,单路会退化成磁盘归并
单路排序看似高效,但前提是 sort_buffer_size 能装下所有行的全部字段。一旦撑爆:
- MySQL 会把数据分块写临时文件,再做多路归并
- 此时 I/O 从顺序变成随机,性能可能比双路还差
-
SHOW PROFILE或 slow log 里会出现Creating sort index+ 大量Copying to tmp table
真正影响选择的不是“哪个更快”,而是“当前配置下哪种更稳”——双路排序的内存压力小、行为可预测;单路排序省 IO 但吃内存,且受字段宽度影响极敏感。


















