index merge是mysql对单表多索引并行扫描后合并结果集(交集/并集/排序并集)的优化技术,能在无联合索引时提升多条件查询效率,但依赖数据分布与回表开销,并非万能方案。

Index Merge 是什么,它真能提升效率?
不是所有多条件查询都适合用 Index Merge;它在特定场景下有效,但多数时候是优化器“没得选”时的妥协方案。MySQL 5.0+ 支持该特性,但默认开启,且仅对单表生效。它本质是让优化器分别扫描多个索引(比如 INDEX(a) 和 INDEX(b)),再对结果集做交集、并集或排序并集合并。实际性能取决于数据分布和回表开销:若合并后仍需大量回表,可能比一个覆盖联合索引还慢。
什么时候会触发 Index Merge Intersection(AND 场景)
当 WHERE 中多个等值条件(a = ? AND b = ?)各自有单列索引,但没有联合索引时,优化器可能选择 index_merge intersection。执行计划中 type 显示为 index_merge,Extra 出现 Using intersect(a,b)。
- 必须是独立的等值条件(不能含函数、表达式或隐式转换)
- 各索引字段不能存在前缀索引截断(如
INDEX(name(10))可能被忽略) - 如果已有
INDEX(a,b),优化器通常不会走 intersection——因为联合索引更优 - 注意:InnoDB 主键范围查询(如
id BETWEEN ? AND ?)也可能参与 intersection,但实际意义有限
OR 条件下 Union Merge 的典型陷阱
WHERE a = 1 OR b = 2 容易触发 index_merge union,看起来很美,但容易踩坑:
- 每个分支索引扫描后需去重合并,CPU 和临时内存开销明显上升
- 若其中任一条件返回大量行(比如
b = 2匹配 80% 的记录),合并代价远超全表扫描 - UPDATE/DELETE 使用 OR + Index Merge 时可能引发死锁(见死锁日志中
UPDATE ... WHERE x = ? AND y = ?并发执行失败) - 更稳的替代方案是改写为
UNION ALL(确保无重复且可分别走索引),或直接补上联合索引INDEX(a,b)
如何判断是否该禁用 Index Merge
当发现慢查询执行计划里频繁出现 type: index_merge,且 rows 预估偏高、实际 Handler_read_* 值异常大时,应怀疑 Index Merge 是否合适。可通过以下方式验证:
- 临时关闭:执行
SET SESSION optimizer_switch='index_merge=off';后重跑 EXPLAIN - 强制走某索引测试:加
USE INDEX (idx_covering)看是否更快 - 检查真实负载:用
pt-index-usage或SELECT ... INTO DUMPFILE分析慢日志中的实际索引命中率,而非依赖预估 - 特别注意:在高并发 UPDATE 场景下,哪怕只是读取阶段用了 Index Merge,也可能放大锁竞争粒度
真正关键的点往往不在“能不能用”,而在于“值不值得让它用”——联合索引宽度控制、字段顺序、以及是否覆盖查询所需列,这些细节比依赖 Index Merge 更可控、更稳定。











