UNION ALL 比 UNION 快的关键在于避免去重和隐式排序开销;UNION 会触发 Using temporary 和 Using filesort,导致全量扫描;列数、类型、别名须严格对齐;ORDER BY/LIMIT 需包裹整个 UNION ALL;业务要求去重时才用 UNION。

直接用 UNION ALL 替代 UNION,只要两个结果集天然无重或业务上允许重复,就能避开去重和隐式排序的开销——这不是“能用就行”的取舍,而是查 100 万行时快 11 倍的关键动作。
为什么 UNION 会突然变慢?看执行计划里的 Using temporary
当你发现 UNION 查询比单个子查询慢几倍,EXPLAIN 输出里却出现 Using temporary 和 Using filesort,基本可以断定:MySQL 正在把所有结果先塞进临时表,再逐行比对去重、再排序。这个过程不依赖索引,纯靠内存/磁盘暴力扫描。
- 去重不是按主键或某列判断,而是整行字段类型+值+NULL 全部严格一致才算重复
- 哪怕你只想要“手机号不重复”,
UNION也会把地址、创建时间等所有列一起比 - MySQL 8.0.19+ 虽然取消了默认排序,但去重逻辑仍在,
Using temporary不会消失
UNION ALL 列数、类型、别名怎么对齐才不报错
UNION ALL 对结构一致性要求极严,报错信息(如 ERROR 1222 (21000): The used SELECT statements have a different number of columns)往往不指明哪一列错了,得自己逐列核对。
- 列数必须完全相等,少一列或多一列都直接报错,不会自动补
NULL - 对应列类型要兼容:比如
TINYINT和INT可隐式升为INT,但VARCHAR(10)和VARCHAR(255)会按长的定宽,若后续用于GROUP BY可能因长度超限导致索引失效 - 列名以第一个
SELECT为准;想统一显示名,只能在第一个子句里用AS起别名,比如SELECT id AS user_id FROM t1 UNION ALL SELECT uid AS user_id FROM t2 - 遇到
TEXT和VARCHAR混用,可能触发截断警告,建议提前用CAST(col AS CHAR)显式对齐
ORDER BY 和 LIMIT 写在哪?为什么总不生效
UNION ALL 语句末尾的 ORDER BY 或 LIMIT 默认只作用于整个合并结果,但如果你没加括号,数据库可能只把它当成最后一个子查询的修饰——而这是非法的。
- 正确写法是把整个
UNION ALL当作子查询包裹起来:SELECT * FROM ( SELECT id, name FROM order_2025_q4 UNION ALL SELECT id, name FROM order_2026_q1 ) AS t ORDER BY id DESC LIMIT 100
- 如果只在最后一个子句后加
ORDER BY id,MySQL 会报错This type of clause is not allowed in a UNION - 大数据量下慎用外层
ORDER BY:它会导致全量合并后再排序,临时表可能撑爆内存;优先考虑是否能在每个子查询内按需排序+限制,比如分页场景下改用SELECT ... FROM t1 ORDER BY id DESC LIMIT 50 UNION ALL SELECT ... FROM t2 ORDER BY id DESC LIMIT 50
什么时候必须用 UNION,而不是偷懒换 UNION ALL
别因为性能好就无脑换。有些场景 UNION ALL 会掩盖数据问题,反而更难排查。
- 合并用户注册表和测试账号表:同一手机号可能在两边都存在,业务要求最终列表唯一 → 必须用
UNION - 后续还要
JOIN或GROUP BY:如果去重逻辑本该由聚合完成(比如统计各渠道新增用户数),那用UNION ALL更合理,避免UNION的中间排序干扰索引使用 - 查的是不同日期分区表(如
log_20260401和log_20260402),且表结构完全一致 →UNION ALL是唯一合理选择 - 开发环境小数据无所谓,但上线前必须跑
EXPLAIN确认没有Using temporary;有,就得立刻定位是UNION还是其他地方拖慢了查询
最常被忽略的一点:字段类型隐式转换带来的索引失效风险,比性能损耗更隐蔽。比如一个子查询用 VARCHAR(16),另一个用 CHAR(8),UNION ALL 后该列实际类型变成 VARCHAR(16),但优化器可能误判 selectivity,导致本该走索引的 WHERE 条件退化为全表扫描。











