导读:本期聚焦于小伙伴创作的《MySQL中MERGE、UNION、MERGE_UNION和SORT_UNION索引合并有什么不同?》,敬请观看详情。执行计划里出现Using intersect、Using union或者Using sort_union时,很多人分不清优化器到底用了哪种索引合并。MySQL在查询带多个等值或范围条件的单列索引时,会通过index merge机制分别扫描再合并结果。MERGE是统称,UNION指对多个索引的ROWID取并集且不排序,适合多个OR等值条件;MERGE_UNION常指这种并集合并的统称;SORT_UNION则在索引返回有序性不足时先排序ROWID再合并,用于OR连接的范围查询。理解它们的触发条件和代价差异,能帮我们判断是否需要建联合索引来避免额外排序与归并开销。

在MySQL的查询优化过程中,当WHERE子句包含多个针对单列索引的条件且彼此以OR或AND连接时,优化器可能会选择索引合并(index merge)访问方式。其中MERGE是这类算法的统称,而UNION、MERGE_UNION与SORT_UNION则是具体的合并策略。它们最核心的区别在于如何扫描多个索引以及如何处理拿到的行指针(ROWID)。

MySQL中MERGE、UNION、MERGE_UNION和SORT_UNION索引合并有什么不同?

一、什么是索引合并中的MERGE

MERGE并不是某一种独立算法,而是MySQL对“同时利用多个索引然后合并结果”这一类访问路径的统称。在EXPLAIN输出的Extra列中,你可能会看到Using index merge,这说明优化器没有选择全表扫描,也没有强行只用其中一个索引,而是分头扫描多个索引,再把中间结果按规则合并。

这种机制的出现,是因为早期MySQL版本不允许在单个查询里同时使用两个独立索引。后来引入了index merge,才使得形如WHERE a=1 OR b=2这样的条件可以分别走idx_a和idx_b,再合并主键。MERGE之下具体分为交集(intersect)、并集(union)和排序后并集(sort_union)等类型,日常讨论里的MERGE_UNION往往就是指并集合并这一类。

二、UNION与MERGE_UNION的执行逻辑

当查询条件是多个等值匹配的OR关系,例如WHERE col1=10 OR col2=20,并且col1、col2上各有独立索引,优化器可能采用UNION合并。它分别通过两个索引拿到符合条件的ROWID集合,由于每个索引在等值查找时返回的主键本身就是有序的,因此可以直接做归并取并集,不需要额外排序。

在MySQL源码与官方文档语境中,这种“对多个索引扫描结果取并集”的策略常被称为union merge,也就是很多资料写的MERGE_UNION。下面是一个简单的表结构和触发示例:

CREATE TABLE user (
  id INT PRIMARY KEY,
  age INT,
  city VARCHAR(50),
  INDEX idx_age (age),
  INDEX idx_city (city)
);

EXPLAIN
SELECT * FROM user
WHERE age = 25 OR city = 'beijing';

如果Extra显示Using union(idx_age,idx_city),就说明走了UNION合并。它的优点是避免了全表扫描,且因为等值查询返回的ROWID有序,合并代价较低;缺点是仍要维护多个索引扫描游标,并在Server层做去重。

三、SORT_UNION适用的场景与代价

当OR连接的条件里包含范围查询,例如WHERE age > 20 OR city < 'z',单个索引返回的行指针顺序未必能直接归并,优化器就会选择SORT_UNION。它会先分别从各索引取出ROWID,放入内存或临时文件排序,再有序合并去重。

相比UNION,SORT_UNION多了一道排序操作,因此在EXPLAIN中你会看到Using sort_union(idx_age,idx_city)。下面的代码展示了范围OR条件可能触发该策略:

EXPLAIN
SELECT * FROM user
WHERE age > 30 OR city < 'shanghai';

由于排序可能涉及磁盘临时表,SORT_UNION通常比UNION更重。如果业务频繁出现这类查询,更合理的做法是评估能否建立联合索引,或者改写SQL,让优化器走更高效的访问路径。

四、三者在执行计划与性能上的对比

我们可以用一张表来归纳它们的差异:

合并类型典型条件是否需要排序EXPLAIN标识
UNION / MERGE_UNION多个等值ORUsing union(...)
SORT_UNION含范围查询的ORUsing sort_union(...)
MERGE(统称)上述各类合并的总称视子类而定Using index merge

从性能角度讲,UNION因为免排序通常最快,SORT_UNION在大数据量下可能因排序产生明显开销。MERGE作为总称,本身不决定效率,真正要看的是它下属的具体合并方式。索引合并虽好,但往往意味着缺少更合适的联合索引,长期应通过表结构优化来减少对其依赖。

五、如何判断是否该干预索引合并

如果你在慢查询日志中发现大量Using sort_union,且扫描行数很高,可以先用optimizer_switch观察关闭索引合并后的计划,再决定是保留还是改索引。例如建立(age, city)的联合索引,可能让查询直接走ref或range,彻底避开合并。

需要注意的是,索引合并受index_mergeindex_merge_unionindex_merge_sort_union等开关控制。生产环境调整前应在测试库验证,避免误关union导致原本高效的查询退化为全表扫描。

-- 查看当前优化器开关
SHOW VARIABLES LIKE 'optimizer_switch';

-- 临时关闭sort_union观察影响
SET optimizer_switch = 'index_merge_sort_union=off';
EXPLAIN
SELECT * FROM user WHERE age > 30 OR city < 'shanghai';

理清MERGE、UNION与SORT_UNION的差异,不只是为了读懂执行计划,更能指导我们判断索引设计是否合理,从而在根本上减少不必要的合并与排序开销。

MySQLindex_mergeunion_merge修改时间:2026-08-07 01:00:27

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。