MySQL 8.0索引跳跃扫描仅在InnoDB表、前导列低基数(≤10–20)、查询跳过最左列且仅用后续列等值条件、优化器估算成本更低时自动触发,无法强制启用,也不适用于JOIN/GROUP BY/ORDER BY等场景。

MySQL 8.0 的索引跳跃扫描(Index Skip Scan)不是手动启用的功能,它只在满足严苛条件时由优化器自动选择;盲目依赖它替代合理建索引,反而会让查询更慢。
如何确认你的查询是否真触发了跳跃扫描
别信 EXPLAIN 的 type 或 key 字段——它们不会暴露跳扫行为。必须用树形执行计划验证:
- 执行
EXPLAIN FORMAT=TREE SELECT * FROM t WHERE b = 5; - 若输出中出现
-> Index skip scan或using_index_skip_scan,才算真正启用 - 若只看到
type: ALL或type: index且key为空,说明没触发——此时应立刻查SELECT COUNT(DISTINCT a) FROM t;,确认前导列a的实际唯一值数量
为什么 USE INDEX(idx_ab) 无法强制跳扫
USE INDEX 和 FORCE INDEX 只能强制使用某个索引,但**不能绕过跳扫的触发前提**:
- 即使加了
USE INDEX (idx_gender_age),若gender有 200 个不同值,优化器仍会放弃跳扫,改走全表扫描 - 隐式类型转换(如
WHERE age = '30'但age是INT)会导致索引失效,跳扫自然也不会发生 - 查询含
ORDER BY b或GROUP BY b时,跳扫结果无法保证全局有序,优化器会直接排除该路径
什么情况下该立刻放弃跳扫,改用单列索引
跳扫本质是“对前导列每个值做一次子扫描”,I/O 放大效应极强:
- 前导列
COUNT(DISTINCT)从 5 升到 50,磁盘随机读次数就翻 10 倍,很可能比全表扫描还慢 - 查询需回表(如
SELECT *而索引不覆盖所有字段),每次子扫描都要取主键再查聚簇索引,延迟成倍叠加 - 业务中
b列被高频单独查询(如WHERE created_at > ?),直接建INDEX (created_at)更稳、更快、更可控
最常被忽略的一点:跳扫只在 InnoDB 表生效,MyISAM 完全不支持;而且它不参与 JOIN 条件推导、不加速 GROUP BY 输出顺序——这些地方指望它,等于把问题藏得更深。


















