mysql集合查询适合什么场景_mysql使用建议说明

来源:这里教程网 时间:2026-02-28 20:37:58 作者:

MySQL 集合查询(

UNION
UNION ALL
INTERSECT
EXCEPT
)不是万能的去重或合并工具,用错场景反而拖慢查询、掩盖数据问题。

什么时候必须用
UNION
而不是多次
SELECT

核心判断点:结果集结构一致,且业务逻辑上属于「同一类数据的不同来源」。

用户表分库分表后需统一查活跃用户:
SELECT id, name FROM user_shard_1 WHERE last_login > '2024-01-01' UNION SELECT id, name FROM user_shard_2 WHERE last_login > '2024-01-01'
订单状态分散在不同表(如
order_normal
order_refund
),但前端需要统一列表展示,字段顺序和类型必须严格对齐
UNION
会自动去重并排序,如果不需要去重,务必改用
UNION ALL
,否则隐式
DISTINCT + ORDER BY
开销极大
MySQL 8.0.19+ 才原生支持
INTERSECT
EXCEPT
,低版本得用
INNER JOIN
NOT EXISTS
模拟,别硬套语法

UNION ALL
性能比
UNION
高多少?

不是“高一点”,而是量级差异——尤其在百万级以上结果集。

UNION
内部等价于
UNION ALL + GROUP BY
(或临时表去重),涉及磁盘临时表、排序、哈希计算
UNION ALL
只做结果集拼接,无额外逻辑,执行计划里看不到
Using temporary; Using filesort
实测:两个各返回 50 万行的子查询,
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 或应用层聚合更稳。

要查「A 表有但 B 表没有」的数据,优先写
LEFT JOIN ... WHERE b.id IS NULL
,比
SELECT ... EXCEPT SELECT ...
兼容性好、执行计划更可控
多条件动态组合查询(比如搜索页的「价格区间 + 品类 + 标签」),用
OR
/
IN
/ 条件拼接通常比多个
UNION
快,且便于加索引
子查询结果集很小(UNION 涉及 5 张表,不如应用层拉回内存做集合运算,避免 MySQL 多次全表扫描
UNION
无法下推谓词(WHERE 条件不能下压到每个子查询内部优化),而单独写多个
SELECT
可分别走索引
SELECT id, title FROM news WHERE status = 1 AND created_at > '2024-01-01'
UNION ALL
SELECT id, title FROM articles WHERE status = 2 AND created_at > '2024-01-01';

真正麻烦的不是语法,是字段对齐、类型收敛、执行计划不可控这三件事。线上跑着的

UNION
查询,建议用
EXPLAIN FORMAT=TREE
看是否用了临时表——如果看到
materialize
,基本就是性能隐患了。

相关推荐