MySQL的select distinct ..Union all和select..union的区别

union和union all去重SQL真实案例

以下是真实的生产业务SQL,我只是把表名更换了一下:(就是捞取两张表的两列数据再去重)

sql 复制代码
SELECT DISTINCT user_id, user_name
FROM (
    SELECT DISTINCT
           manager_id AS user_id,
           manager_name AS user_name
    FROM demo_order_detail
    WHERE status = 1

    UNION ALL

    SELECT DISTINCT
           operator_id AS user_id,
           operator_name AS user_name
    FROM demo_task
    WHERE status = 1
) t;

上面的SQL中,用了union all,那么我们用两个测试表看一下select distinct union all和直接用select union它们的执行过程树形图是什么样的:

只有select union的SQL场景

他的过程是:

sql 复制代码
user
 ↓
recharge
 ↓
边合并边物化,并在这个 UNION 结果层完成去重

select distinct union all的SQL场景

他的过程是:

sql 复制代码
user
 ↓
recharge
 ↓
先全部 UNION ALL
 ↓
形成完整的 t
 ↓
再扫描 t
 ↓
重新建临时表
 ↓
最后 DISTINCT 去重

数据量很小的时候,这两种SQL的差异是很难凸现出来的,那么我们试一下更大的百万级数据量。

百万计数据量时,两种性能的对比

测试表结构:

sql 复制代码
-- 用户表
CREATE TABLE user (
    id INT PRIMARY KEY,
    name VARCHAR(20)
);


-- 用户充值表
CREATE TABLE recharge (
    id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    KEY idx_user_id (user_id)
);

我们先看下表数据量(100万用户,300万条充值流水):

分别explain看执行计划

只有union的过程

sql 复制代码
recharge 300万
↓
idx_user_id 覆盖索引扫描
↓
第一次去重
300万 → 10万
↓
UNION ALL
↓
最终 DISTINCT
↓
100万

这个执行过程生成耗时4.35s

union al加distinct的过程

sql 复制代码
user 100万
       \
        UNION ALL
       /
recharge 300万
↓
中间结果约 400万
↓
再做一次最终 DISTINCT
↓
100万

生成执行计划耗时9.44秒,明显比直接union的慢了不少。

再看下他们的真实SQL执行上差距,防止内存或者磁盘溢出,我直接通过count(*)来对比他们的性能:

由此可见,百万数量级直接union的性能比union all distinct的高大概30%。

把recharge充值表数据量提高到千万级别select尝试:

依然是快了30%左右,这绝对是非常实用的一个优化点!

相关推荐
2501_930472441 小时前
深度复盘|数据库迁移实战(下):从自建 MySQL 5.7 到腾讯云 MySQL 8.0 的 SQL 兼容改造
数据库·mysql·腾讯云
2501_930472441 小时前
深度复盘|数据库迁移实战(上):腾讯云助手解析慢查询日志,定位索引缺失与语法不兼容
数据库·阿里云·ffmpeg·云计算·腾讯云·aws
SelectDB技术团队1 小时前
从 ClickHouse 迁移到 Doris:SQL 兼容、同步与验证清单
数据库·人工智能·sql·clickhouse·apache doris·selectdb·湖仓架构升级
leo_messi941 小时前
Mysql学习(十二) -- SQL执行到底做了什么事?
sql·学习·mysql
敲代码的嘎仔1 小时前
从零实现视频续播 + 学习进度统计:前端心跳、条件更新、GROUP BY 统计全链路拆解
java·前端·数据库·学习·面试·职场和发展·音视频
草莓熊Lotso1 小时前
【Redis 初阶】C++ 客户端实战:从 RESP 协议到 redis-plus-plus 工程化用法
linux·开发语言·网络·数据库·c++·redis·缓存
dunge20261 小时前
2026年9月11日|ChatGPT Pro + Codex:GPT‑6 Astra 数据库性能优化
数据库·gpt·chatgpt
NeilYuen2 小时前
【kv存储】结合faiss构建向量内存数据库
数据库·faiss
风哥2号2 小时前
数据库教程FGMT18‑Oracle‑EMCC智能化集中运维管理系统
运维·数据库·oracle