开放问答
MySQL 8.0 有 (a,b) 联合索引,WHERE a IN(...) + ORDER BY b 仍触发 filesort,怎么判断该改索引还是改 SQL
该问题的正文、回答与评论。
提问者 陈若衡-152 · 状态 open
MySQL索引EXPLAIN慢查询filesort
背景:订单表 t_order 约 4200 万行,InnoDB,MySQL 8.0.32,已建联合索引 idx_ab (a, b),其中 a 是商户ID(高基数,单值查询命中 200~3000 行不等),b 是创建时间(datetime)。
现象:一条高频查询 SELECT id, a, b FROM t_order WHERE a IN (1001,1002,1003,1004,1005) ORDER BY b DESC LIMIT 20,EXPLAIN 显示 type=range、key=idx_ab、Extra=Using filesort;当 IN 列表里 5 个商户合计命中约 8000 行时,单次 120~300ms,P99 抖动明显。
已尝试与结果:
- 把索引改成 (a, b DESC) —— 8.0 支持降序索引,但 EXPLAIN 依旧 filesort,说明 IN 多值场景下优化器没走索引有序;
- 把 IN 拆成 5 个子查询各 ORDER BY b LIMIT 20 再在应用层归并 —— 正确性没问题,但想确认这是不是唯一解;
- 查过慢日志,rows_examined 约等于命中行数,没有全表扫,确认不是统计信息失效。
卡点:我不确定 8.0 在这种「高基数 a 的 IN 多值 + ORDER BY b + LIMIT」组合下,优化器到底有没有可能走索引序而避免 filesort?以及判断「该继续调索引/改写」还是「该上覆盖索引或缓存」的量化依据是什么(比如 rows × 单行代价的阈值)?
期望答案形态:能给出 1) 一个可复现的判断口诀或代价模型;2) 针对 IN 多值 + ORDER BY 的几种改写对比与适用条件;3) 如果确实无解,推荐的兜底方案排序。
评论
暂无评论。