UNION会触发去重和默认排序,UNION ALL仅拼接且无额外开销;大数据量下UNION性能远低于UNION ALL,如100万行时慢11倍,主因I/O与内存压力;是否使用UNION仅取决于业务是否需要去重。

UNION会触发去重+排序,UNION ALL只是拼接
UNION不是简单合并,它等价于先UNION ALL再DISTINCT,还要默认排序(除非显式加ORDER BY)。数据库引擎必须建临时表、做全量比较、排序,才能剔掉重复行。而UNION ALL直接把各子查询结果流式输出,零额外处理。
大数据量下性能差距可达10倍以上
实测中,100万行数据合并时:UNION ALL耗时约810ms,UNION高达9200ms——慢了11倍。瓶颈不在CPU,而在I/O和内存:
-
UNION常触发Using temporary和Using filesort(MySQLEXPLAIN可见) - 临时表写入SSD带来延迟,内存不足时还会换出到磁盘
- 排序破坏原有索引顺序,后续WHERE或JOIN可能失效
哪些场景必须用UNION?哪些能放心换UNION ALL?
判断依据只有一个:你是否真的需要去重。
- 必须用
UNION:跨系统拉客户数据(CRM + 旧库),字段相同但ID可能重复;统计口径不同但需合并去重的报表维度 - 可直接换
UNION ALL:按时间分表的日志查询(log_2023+log_2024)、分库用户表(user_shard1+user_shard2,ID全局唯一)、CTE中间结果拼接 - 容易踩坑:以为两个子查询“肯定没重复”,结果因NULL值或隐式类型转换导致重复未被识别——
UNION才真正保险
列匹配和类型兼容性对两者一视同仁
UNION和UNION ALL都强制要求:子查询列数一致、对应列类型兼容(如INT和TINYINT可隐式转换,VARCHAR和TEXT在多数引擎中也可)。不满足时,两者报错完全一样:ERROR 1222 (21000): The used SELECT statements have a different number of columns或类型冲突提示。
UNION图省事;先确认业务是否允许重复,再决定要不要承担那多出来的排序和去重开销。


















