

新闻资讯
技术学院必须用UNION而非多次SELECT的核心场景是结果集结构一致且业务逻辑属同一类数据不同来源,如分库分表查活跃用户或合并订单状态表;需严格对齐字段顺序与类型,去重需求明确时才用UNION,否则优先UNION ALL以避免隐式排序与去重开销。
MySQL 集合查询(UNION、UNION ALL、INTERSECT、EXCEPT)不是万能的去重或合并工具,用错场景反而拖慢查询、掩盖数据问题。
UNION 而不是多次 SELECT
核心判断点:结果集结构一致,且业务逻辑上属于「同一类数据的不同来源」。
SELECT id, name FROM user_shard_1 WHERE last_login > '2025-01-01' UNION SELECT id, name FROM user_shard_2 WHERE last_login > '2025-01-01'
order_normal 和 order_refund),但前端需要统一列表展示,字段顺序和类型必须严格对齐UNION 会自动去重并排序,如果不需要去重,务必改用 UNION ALL,否则隐式 DISTINCT + ORDER BY 开销极大INTERSECT 和 EXCEPT,低版本得用 INNER JOIN 或 NOT EXISTS 模拟,别硬套语法UNION ALL 性能比 UNION 高多少?不是“高一点”,而是量级差异——尤其在百万级以上结果集。
UNION 内部等价于 UNION ALL + GROUP BY(或临时表去重),涉及磁盘临时表、排序、哈希计算UNION ALL 只做结果集拼接,无额外逻辑,执行计划里看不到 Using temporary; Using filesort
UNION ALL 耗时约 0.12s;UNION 耗时 1.8s 以上(取决于内存配置)UNION ALL;去重要求必须明确来自业务,而非“怕出错就用 UNION”UNION 报错或隐式转换
MySQL 对 UNION 各子句的列类型兼容性很敏感,报错往往不直观。
ERROR 1267 (HY000): Illegal mix of collations —— 字符集/校对规则不一致,比如 utf8mb4_0900_as_cs 和 utf8mb4_general_ci 混用INT 和 VARCHAR 同列位置会触发隐式转换,可能截断或转成 0,例如:SELECT 123 UNION SELECT 'abc' → 第二列转成 123(字符串转数字失败则为 0)CAST 或 CONVERT 统一类型,例如:SELECT CAST(id AS CHAR) FROM t1 UNION SELECT name FROM t2
的,后续子句别名无效,别指望靠别名对齐字段语义UNION 更合适的情况集合操作是语法糖,不是性能银弹。很多场景用单表 JOIN 或应用层聚合更稳。
LEFT JOIN ... WHERE b.id IS NULL,比 SELECT ... EXCEPT SELECT ... 兼容性好、执行计划更可控OR / IN / 条件拼接通常比多个 UNION 快,且便于加索引UNION 无法下推谓词(WHERE 条件不能下压到每个子查询内部优化),而单独写多个 SELECT 可分别走索引SELECT id, title FROM news WHERE status = 1 AND created_at > '2025-01-01' UNION ALL SELECT id, title FROM articles WHERE status = 2 AND created_at > '2025-01-01';
真正麻烦的不是语法,是字段对齐、类型收敛、执行计划不可控这三件事。线上跑着的 UNION 查询,建议用 EXPLAIN FORMAT=TREE 看是否用了临时表——如果看到 materialize,基本就是性能隐患了。