订单列表按 status 过滤再按 create_time 倒序,explain 的 Extra 里是 Using filesort,慢日志记了 2.4 秒。sort_merge_passes 一直在涨。碰到这种情况,我一般先确认改动有没有真的生效。
原因不复杂,过滤用的索引只排了 status,取出的行在 create_time 上无序,数据库只能把结果全取出来再排。行数一多就落到磁盘做归并,多轮 merge 之后耗时按 GB 算。
碰到「filesort 排序」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。报错里带路径的,先去看那个路径在不在、权限对不对。
ALTER TABLE orders ADD INDEX idx_status_ctime (status, create_time DESC); EXPLAIN SELECT id, create_time FROM orders WHERE status = 1 ORDER BY create_time DESC LIMIT 20;
同一份配置存在多处的,先确认改的是被加载的那一份。新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。
备份不是备了就行,恢复一次才算数,很多备份文件打开才发现是空的。
具体做法是,建 (status, create_time) 联合索引 让过滤和排序共用一棵树;排序方向要和索引一致 倒序就建降序索引;确认 select 的列没有触发额外回表排序 必要时把排序列一起覆盖;改完看 Extra 里 filesort 是否消失。
最后用这个标准收尾,Extra 里不再出现 Using filesort 查询耗时从 2.4 秒降到 20 毫秒以内。
