index merge是mysql优化器在无合适联合索引时的fallback策略,非主动启用;explain中type=index_merge表示并行扫描多个二级索引后合并主键结果集,性能通常较差且不稳定。

index_merge 不是主动“启用”的策略,而是 MySQL 优化器在单表查询中、实在没更好选择时自动 fallback 的行为。它不快,也不稳定,但确实存在——关键是你得知道它什么时候冒出来、为什么冒出来、以及怎么让它少露面。
EXPLAIN 中看到 type=index_merge 意味着什么
这表示优化器放弃了单索引扫描,转而并行扫描多个二级索引,再合并主键结果集。不是“更优”,而是“权衡后勉强可接受”。
-
key字段会列出实际参与的索引名,比如idx_age,idx_status -
Extra字段明确告诉你用了哪种合并:Using intersect()(AND 等值)、Using union()(OR 等值)、Using sort_union()(OR 含范围条件) - 如果
rows总和远大于表总行数(例如两个索引各返回 50w 行),说明合并开销巨大,几乎等价于扫表 + 额外 CPU
WHERE a = ? OR b = ? 为什么容易触发 index_merge_union
这是最常见触发场景:两个字段各自有单列索引,且条件用 OR 连接。
- 必须是独立等值匹配(
=、IN),不能含函数、隐式转换或范围操作(如a > 10 OR b = 'x'会走sort_union,性能更差) - 若其中任一条件能走
const或eq_ref(比如主键等值),优化器大概率直接跳过合并,选那个最优索引 - 注意 ORM 自动生成的
id IN (…)查询,也可能意外激活index_merge_union,不如显式建覆盖索引
WHERE a = ? AND b = ? 走 index_merge_intersection 的真实前提
别以为只要 AND 就一定触发交集合并——它要求极其严格:
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
- 每个条件必须命中**完整前缀的等值匹配**:比如有索引
idx_a和idx_b,才可能合并;但若有联合索引idx_a_b,只用a = ?就不会参与 intersection - 数据分布影响极大:如果
b = ?匹配 90% 的行,优化器宁可全表扫,也不会做交集计算 + 回表 - MySQL 8.0 对
index_merge_intersection更激进,有时误判成本,反而选错执行计划
比依赖 index_merge 更靠谱的三件事
它只是兜底手段,不是设计目标。真正要做的不是“怎么用好它”,而是让它没机会出场:
- 优先建联合索引:比如高频查
WHERE status = ? AND type = ?,直接建INDEX(status, type),性能通常比index_merge快 2–5 倍 - 删掉冗余单列索引:已有
INDEX(a,b)后,INDEX(a)几乎无价值(除非 a 单独查询极频繁且 b 分布极不均) - 定期刷新统计信息:
ANALYZE TABLE table_name,避免因基数不准导致优化器误判成本,硬推index_merge
真正麻烦的不是看懂 Using intersect(),而是当它出现在慢查询里时,你得意识到:这不是功能亮点,是索引设计漏了洞。










