UNION ALL比UNION快的根本原因是跳过去重+排序链路,纯流式拼接零临时表、零文件排序;UNION强制触发DISTINCT+ORDER BY,需临时结构、哈希/排序及可能磁盘I/O,100万行时慢11倍以上。
UNION ALL 在 SQL 视图中比 UNION 快,根本原因不是“少做了一步去重”,而是它跳过了整个去重+排序的数据处理链路——数据库压根不启动那套机制。
UNION 实际触发的是 DISTINCT + ORDER BY 两层开销UNION 不是“先拼再筛”,而是强制走一套集合归并流程:所有子查询结果必须先写入临时结构(内存或磁盘),再做哈希/排序去重,最后按第一列升序输出(即使你没写 ORDER BY) Using temporary 和 Using filesort,尤其当参与列无索引、数据量超 5 万行时,I/O 和 CPU 成为瓶颈 ORDER BY id,数据库仍可能执行两次排序:一次为去重,一次为你显式指定的顺序 UNION ALL 是纯流式拼接,零中间态SELECT 开始返回数据,第二个紧接着追加,全程保持 pipeline 模式 Using temporary 或 Using filesort,执行计划干净利落 log_202604 和 log_202605)、状态互斥查询(如 status = 1 和 status = 2),UNION ALL 的语义更准确、性能更可预期 UNION ALL 并不宽容:列数不等、类型不兼容(比如 INT 和 JSON)、NULL 性约束冲突(NOT NULL vs NULLable),一样报错 UNION ALL 绕过类型检查——MySQL 8.0+ 在严格模式下,第一条 SELECT 返回 NOT NULL VARCHAR(50),第二条返回 NULL,直接拒绝执行 SELECT 为准,后续子查询中的别名(如 SELECT id AS uid)无效 ORDER BY 是唯一可控排序方式ORDER BY 没用,语法允许但被忽略;UNION 的隐式排序规则不可靠(可能按主键、也可能按表达式推导出的列),UNION ALL 更是完全依赖执行顺序 SELECT id, name FROM users_2023<br>UNION ALL<br>SELECT id, name FROM users_2024<br>ORDER BY id;
真正容易被忽略的,是 UNION 的性能衰减是非线性的——100 万行时慢 11 倍,而嵌套在视图里再套一层 LIMIT OFFSET,代价可能翻倍还不止。