Creating sort index 表示 MySQL 正在执行 filesort,即因无法利用索引排序而被迫在内存或磁盘中额外排序,常见于 WHERE 条件不满足索引有序性时,如 WHERE city = 'Shanghai' ORDER BY id;优化核心是创建符合最左前缀原则的联合索引(如 idx_city_id),使排序字段紧随查询字段之后。

Creating sort index 状态说明
这个状态不是错误,而是 MySQL 正在执行 filesort —— 即无法利用索引完成排序,被迫在内存或磁盘中对结果集做额外排序。它常出现在 EXPLAIN 的 Extra 列里显示 Using filesort,同时 SHOW PROCESSLIST 中看到线程卡在 Creating sort index。本质是排序成本高,尤其当数据量大、sort_buffer_size 不足、或未命中有序索引时。
为什么 ORDER BY id 会触发 Creating sort index
即使 id 是主键且天然递增,只要查询条件没让 MySQL 认定“结果已按 id 有序”,它仍会走 filesort。典型场景:WHERE city = 'Shanghai' ORDER BY id —— 单列 city 索引无法提供 id 顺序,MySQL 只能先查出所有匹配行,再排序。
- 主键顺序 ≠ 查询结果顺序:除非 WHERE 条件本身能通过主键索引范围扫描(如
WHERE id BETWEEN 100 AND 200),否则不自动继承有序性 - 联合索引必须覆盖排序字段且顺序一致:比如
idx_city_id(city, id)才能让WHERE city = ? ORDER BY id跳过filesort - MySQL 8.0+ 支持混合方向(
ASC/DESC),但老版本对ORDER BY id DESC若索引是(city, id ASC),仍可能退化
如何快速验证和定位问题
别猜,直接看执行计划和实际行为:
- 运行
EXPLAIN FORMAT=JSON SELECT ...,重点检查query_block下的using_filesort和using_disk_sort字段是否为true - 查慢日志:开启
log_queries_not_using_indexes = ON,并设long_query_time = 0.1捕获带filesort的短查询 - 监控指标:观察
SHOW GLOBAL STATUS LIKE 'Sort_merge_passes',值持续上升说明频繁落盘排序 - 对比测试:去掉
ORDER BY,若耗时骤降(如从 2s 降到 20ms),基本锁定是排序瓶颈
实操优化策略(按优先级排序)
真正有效的优化不是调参,而是让排序“消失”:
- 建联合索引,把
WHERE字段放前,ORDER BY字段紧随其后,例如CREATE INDEX idx_status_created_at ON orders(status, created_at)对应WHERE status = 1 ORDER BY created_at - 用覆盖索引减少回表:如果只需部分字段,把它们全加进联合索引,
EXPLAIN显示Using index就说明没回表,排序压力更小 - 避免
SELECT *:只取必要字段,降低单行体积,让同样大小的sort_buffer_size能容纳更多行,减少落盘概率 - 临时调大
sort_buffer_size仅限单次操作:如建索引或跑报表,SET SESSION sort_buffer_size = 4194304(4MB),但切记不要改全局配置,否则并发高时易 OOM - 对超大分页(
LIMIT 1000000, 20):改用游标式查询,比如记录上一页最大id,下一页用WHERE id > ? ORDER BY id LIMIT 20,彻底避开深偏移排序
最易被忽略的一点:即使你建了 (a, b) 索引,如果查询写成 WHERE b = ? ORDER BY a,依然触发 Creating sort index —— 最左前缀原则不是摆设,字段顺序必须和索引定义严格一致。


















