UNION ALL 后再聚合性能更好,因其避免中间去重与排序,将去重逻辑交由 GROUP BY 一次性完成;当子查询天然无交集时,UNION 先去重再聚合属冗余计算,而 UNION ALL + GROUP BY 仅触发一层聚合,执行计划更优、下推优化更可行。

UNION ALL 后再聚合性能更好,是因为它把去重逻辑从中间层移到了最终聚合点,避免了重复的临时表和排序开销——尤其当子查询本身已天然无交集时,UNION 先去重再聚合,等于做了两遍无效计算。
UNION ALL + GROUP BY 比 UNION + GROUP BY 少一次去重
常见错误现象:写 SELECT id FROM t1 UNION SELECT id FROM t2 GROUP BY id,以为能“先合并去重再分组”,实际执行顺序是先 UNION(触发 Using temporary 和 Using filesort),再对已去重结果 GROUP BY。而 SELECT id FROM t1 UNION ALL SELECT id FROM t2 GROUP BY id 是先拼接、再一次性聚合,去重逻辑由 GROUP BY 完成。
- UNION 会强制在子查询结果上做 DISTINCT,哪怕你后续还要 GROUP BY,这部分去重就是冗余的
- UNION ALL 不产生中间去重,
GROUP BY直接面对原始行流,优化器更可能利用索引或哈希聚合 - EXPLAIN 中能看到:前者有两层
Using temporary(UNION 一层,GROUP BY 一层),后者通常只有一层
聚合字段类型不一致时,UNION ALL 更早暴露问题
比如一个子查询返回 NOT NULL INT,另一个返回 NULL INT,用 UNION 可能隐式转换成功但慢;而 UNION ALL 在 MySQL 8.0+ 严格模式下直接报错 ERROR 1052: Column 'x' in field list is ambiguous 或类型冲突,逼你提前修复结构。
- 列类型兼容性检查在 UNION/UNION ALL 阶段就发生,不是等到 GROUP BY 才校验
- UNION 的隐式转换可能掩盖数据质量问题,比如 VARCHAR 和 TEXT 混用导致排序规则不一致,影响 GROUP BY 结果准确性
- 早点报错比查出来一堆空值或乱序分组更可控
嵌套视图里用 UNION ALL + 外层聚合更容易下推优化
如果你把 SELECT a, COUNT(*) FROM (SELECT x AS a FROM t1 UNION ALL SELECT y AS a FROM t2) t GROUP BY a 封装成视图,MySQL 8.0+ 有机会将 GROUP BY 下推到每个子查询里并行计算,再汇总;但换成 UNION,优化器大概率放弃下推,因为去重破坏了子查询独立性。
- UNION ALL 保持各子查询语义隔离,优化器更敢拆分执行
- UNION 强制要求全量拉取后再处理,无法跳过某一分片或提前终止
- 带
LIMIT的聚合查询(如 TopN)在 UNION ALL 场景下也更可能被优化为 partial aggregate + merge,UNION 则基本没戏
真正容易被忽略的是:聚合前是否真需要全局去重。如果两个子查询按时间/状态/分区键天然互斥(如 status = 1 和 status = 2),UNION 的去重不仅慢,还可能因隐式排序干扰 GROUP BY 的哈希分布策略——这时候用 UNION ALL + GROUP BY 不是“省事”,而是让执行计划回归可控。


















