INDEX_SKIP_SCAN仅用于单表查询,不参与JOIN连接逻辑;它只在满足8个特定条件时由优化器自动启用,且与JOIN算法(如NLJ、Hash Join)完全独立。

INDEX_SKIP_SCAN 不用于 JOIN 连接场景 —— 这是关键前提,必须先厘清。
MySQL 的索引跳跃扫描(INDEX_SKIP_SCAN)仅作用于单表查询,且只在满足特定条件时由优化器自动启用。它从不参与多表 JOIN 的驱动表选择、连接顺序或连接算法(如 Nested Loop / Hash Join)决策。
如果你在 EXPLAIN 输出中看到 Using index for skip scan 同时又存在 JOIN,那说明:
- 跳跃扫描只发生在其中一张表(通常是被驱动表)的 单表 WHERE 条件过滤阶段;
-
JOIN本身仍由其他机制处理(比如用主键/外键走ref或eq_ref); - 两者是并行发生的独立优化行为,不是“因为要 JOIN 才启用跳跃扫描”。
常见误解来源:
- 把
Extra列里同时出现的Using index for skip scan和Using join buffer当作因果关系; - 看到慢查询含
JOIN和联合索引,误以为跳跃扫描在“帮 JOIN 加速”; - 没注意执行计划中各表的
type和key字段 —— 跳跃扫描只会出现在某一行的key非空、type为range或ref、且Extra明确标注该提示的位置。
真正影响 JOIN 性能的关键点:
- 驱动表是否能用上高效访问类型(
const/eq_ref); - 被驱动表的关联字段是否有合适索引(最好是覆盖索引);
-
ON条件是否符合最左前缀,或能否触发INDEX_SKIP_SCAN(仅当该表是单表过滤 + 关联字段恰在联合索引非首列时); - 数据分布是否导致优化器误判:比如首列基数过高(如
user_id),即使写了WHERE b = ?,优化器也会弃用跳跃扫描,改走全表扫描 —— 此时加FORCE INDEX也无效,因为INDEX_SKIP_SCAN不能强制启用。
容易被忽略的细节:
-
INDEX_SKIP_SCAN的启用完全由优化器自主决定,没有 SQL 提示(如USE INDEX)能直接触发它; - 它对
GROUP BY、DISTINCT、子查询中的IN等场景有额外限制,一旦出现这些结构,即使单表条件匹配,也可能跳过该优化; -
ANALYZE TABLE必须及时执行 —— 如果统计信息陈旧,优化器看不到首列低基数特征,就不会考虑跳跃扫描。
所以当你怀疑“为什么 JOIN 用了跳跃扫描”,实际该问的是:“这张被 JOIN 的表,它的 WHERE 条件是否意外触发了单表跳跃扫描?而这个扫描是否真的比建一个更合适的索引更高效?”

















