
UNION与UNION ALL作为SQL集合操作的核心运算符,其性能差异源于数据处理的本质区别:
UNION时,数据库引擎会自动执行以下流程:(SELECT * FROM table1)
UNION
(SELECT * FROM table2)
-- 等价于
SELECT DISTINCT * FROM (
SELECT * FROM table1
UNION ALL
SELECT * FROM table2
) AS combined_data系统需要创建临时表存储中间结果集,执行排序操作消除重复记录。以MySQL为例,通过EXPLAIN可观察到Using temporary和Using filesort标记。UNION ALL采用流式处理机制,仅需顺序扫描各子查询结果集。而UNION的排序去重操作会引发以下额外消耗:通过TPC-H测试数据集进行基准测试(单位:毫秒):
数据量 | UNION ALL | UNION | 差异倍数 |
|---|---|---|---|
10万行 | 82 | 620 | 7.56x |
50万行 | 395 | 3,850 | 9.75x |
100万行 | 810 | 9,200 | 11.36x |
测试环境:MySQL 8.0,InnoDB引擎,SSD存储
随着数据量增长,UNION的时间复杂度呈非线性上升趋势,主要瓶颈出现在:
覆盖索引设计
当UNION必须使用时,为子查询字段创建覆盖索引可减少排序阶段的磁盘I/O。以电商订单合并场景为例:
-- 创建复合索引避免回表
CREATE INDEX idx_order_union ON orders(region, order_date, amount)
-- 优化后的UNION查询
SELECT region, order_date, amount FROM orders_asia
UNION
SELECT region, order_date, amount FROM orders_europe哈希去重替代
在PostgreSQL等支持哈希聚合的数据库中,通过调整配置参数启用哈希去重:
SET enable_sort = off;
SELECT * FROM table1
UNION
SELECT * FROM table2 -- 此时使用HashAggregate而非Sort强制索引使用
当优化器错误选择全表扫描时,使用FORCE INDEX提示:
(SELECT * FROM log_2023 FORCE INDEX(timestamp_idx))
UNION
(SELECT * FROM log_2024 FORCE INDEX(timestamp_idx))临时表优化
通过调整tmp_table_size参数控制内存临时表使用:
# MySQL配置
tmp_table_size = 64M
max_heap_table_size = 64M分片数据预处理
在TiDB等分布式数据库中,先在分片节点去重再汇总:
-- 各分片执行
SELECT DISTINCT * FROM local_table
-- 协调节点执行
SELECT * FROM shard1_result
UNION ALL
SELECT * FROM shard2_result并行执行控制
Oracle开启并行查询加速大数据量合并:
SELECT /*+ PARALLEL(8) */ col1 FROM tab1
UNION ALL
SELECT /*+ PARALLEL(8) */ col1 FROM tab2直接对UNION结果分页会触发全量计算,采用子查询分层处理:
WITH temp AS (
SELECT id, name, 1 AS source FROM big_table1
UNION ALL
SELECT id, name, 2 AS source FROM big_table2
)
SELECT * FROM temp
ORDER BY id LIMIT 100 OFFSET 10000合并JSON字段时需注意格式一致性:
SELECT JSON_EXTRACT(payload, '$.event') AS event
FROM log_2023
UNION ALL
SELECT CAST(data->>'action' AS JSON) -- 显式类型转换
FROM log_2024通过中间件转换字段类型后合并:
-- 从MongoDB和MySQL同步数据
SELECT
_id AS doc_id,
title,
CAST(created_at AS DATETIME)
FROM mongo_articles
UNION ALL
SELECT
id,
title,
publish_time
FROM mysql_articlesUNION ALLUNION成本Extra列中的Using temporary警告# MySQL内存监控
SHOW STATUS LIKE 'Created_tmp%';
# PostgreSQL排序统计
SELECT * FROM pg_stat_database WHERE datname = 'your_db';UNION超时时可分阶段执行: -- 第一阶段:存入临时表
CREATE TEMPORARY TABLE tmp_data AS
SELECT * FROM table1 UNION ALL ...;
-- 第二阶段:去重处理
SELECT DISTINCT * FROM tmp_data;深度思考:在云原生架构下,传统UNION操作面临计算下推与数据分片的新挑战。建议结合物化视图实现预聚合,或采用UNION ALL +窗口函数进行二次去重,例如:
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER(PARTITION BY key_col) AS rn
FROM (
SELECT * FROM shard1
UNION ALL
SELECT * FROM shard2
) merged
) ranked
WHERE rn = 1此模式可将去重压力分散到查询层,避免集中式排序带来的系统性风险。
🌟 让技术经验流动起来
▌▍▎▏ 你的每个互动都在为技术社区蓄能 ▏▎▍▌
✅ 点赞 → 让优质经验被更多人看见
📥 收藏 → 构建你的专属知识库
🔄 转发 → 与技术伙伴共享避坑指南
点赞 ➕ 收藏 ➕ 转发,助力更多小伙伴一起成长!💪
💌 深度连接:
点击 「头像」→「+关注」
每周解锁:
🔥 一线架构实录 | 💡 故障排查手册 | 🚀 效能提升秘籍
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。