mysql的index_merge_union需同时开启index_merge和index_merge_union,且仅在or连接的独立单列等值条件、各字段有高基数单列索引时才触发;性能通常不如联合索引,应优先建合适联合索引而非依赖该优化。

index_merge_union 开启后为啥没走索引合并?
MySQL 的 index_merge_union 不是“开了就自动生效”的开关,它只在优化器判定多个单列索引的并集比全表扫描或单索引更优时才触发。常见现象是:明明开了,EXPLAIN 里却看不到 type=union 或 Extra=Using union(...)。
实操建议:
- 必须确保 WHERE 条件是
OR连接的、彼此独立的单列等值条件(如a = 1 OR b = 2),不能含函数、范围查询(>、BETWEEN)、IS NULL等; - 每个涉及字段都要有独立的单列索引(不是联合索引);
- 用
SELECT ... FROM t WHERE a = 1 OR b = 2这类简单语句测试,避免 JOIN 或子查询干扰优化器决策; - 检查
SHOW INDEX FROM t,确认a和b索引的Cardinality都足够高(低基数字段如状态码通常不触发)。
optimizer_switch 中 index_merge_union 的位置和依赖
index_merge_union 是 optimizer_switch 的一个子项,但它依赖于 index_merge 总开关——如果 index_merge=off,单独开 index_merge_union 无效。
实操建议:
- 查看当前设置:执行
SELECT @@optimizer_switch,搜索是否同时包含index_merge=on和index_merge_union=on; - 安全开启方式:
SET SESSION optimizer_switch='index_merge=on,index_merge_union=on';(会话级,不影响其他连接); - 不要只写
index_merge_union=on,漏掉index_merge=on是最常踩的配置坑; - 全局修改需谨慎:
SET GLOBAL optimizer_switch=...会重置所有未显式指定的子项为默认值,建议完整拼出整个字符串。
union 索引合并 vs 联合索引,哪个更快?
即使 index_merge_union 触发成功,性能也不一定比建一个合适的联合索引好。MySQL 的索引合并要分别扫描多个索引、去重、归并结果集,IO 和 CPU 开销都更高。
YothSHOP是优斯科技鼎力打造的一款asp开源商城系统,支持access和Sql server切换,完善的会员订单管理,全站生成静态html文件,SEO优化效果极佳,后台XP模式和普通模式随意切换,极易操作,欢迎使用! Asp开源商城系统YothSHOP功能介绍:1.使用静态页和程序页分离技术,网站可自由开启和关闭,实现全站生成静态页,可动静态切换,方便二次开发和后期维护。2.管理员管理:后台
实操建议:
- 优先考虑建联合索引:对
WHERE a = ? OR b = ?,INDEX(a), INDEX(b)可能不如INDEX(a,b)或INDEX(b,a)(取决于查询频率和选择性); - 用
SELECT COUNT(*)对比耗时:分别在开启/关闭index_merge_union下执行相同OR查询,看执行时间与Handler_read_*状态变量变化; - 注意数据分布:当两个条件返回行数差异极大(比如一个返回 10 行,另一个返回 10 万行),合并代价可能远超单索引 +
OR逻辑改写(如UNION DISTINCT); - 5.7+ 版本中,
index_merge_intersection在AND场景下更稳定,但union类型始终是优化器最后考虑的备选方案。
EXPLAIN 看不到 Using union?检查这几个地方
EXPLAIN 输出里没出现 Using union(...),不代表没走索引合并——也可能是 MySQL 用了 index_merge_intersection 或降级为 range 扫描。
实操建议:
- 务必加
FORMAT=JSON:执行EXPLAIN FORMAT=JSON SELECT ...,在query_block -> access_type或using_join_buffer上下文里找union字样; - 开启 optimizer trace:
SET optimizer_trace="enabled=on";再执行查询,查information_schema.OPTIMIZER_TRACE,里面会明确写出“considering union access”或“rejected by cost calculation”; - 留意
type字段:如果是index_merge,且key显示多个索引名(如key: a,b),基本可确认触发; - 避免隐式类型转换:比如
WHERE varchar_col = 123会导致索引失效,合并自然也不会发生。
真正难的是判断“该不该开”——它解决的是没有联合索引又不得不写 OR 的临时场景,而不是索引设计的替代方案。线上环境一旦发现 index_merge_union 频繁生效,第一反应应该是补索引,而不是调优开关。









