MySQL查询去重是使用UNION还是使用DISTINCT 标签MySQL、SQL优化、去重、UNION、DISTINCT、UNION ALL、执行计划前言开发过程中经常面临数据去重需求大家常会纠结两种方案使用DISTINCT在单条结果集中完成去重使用UNION合并多条查询并自动去重。还有很多开发者分不清UNION和UNION ALL的巨大差异经常误用导致数据库出现不必要的性能消耗。本文对比两者原理、适用场景、性能差距给出线上环境选型标准。一、先理清基础语法与核心行为1. DISTINCT作用对单条SQL的结果集进行去重。SELECTDISTINCTuser_idFROMuser_login_logWHEREdateCURDATE();执行逻辑数据库取出所有满足条件的数据按照指定字段进行分组对比剔除重复行保留唯一记录。2. UNION 与 UNION ALL重点区分-- UNION合并结果 自动去重 排序SELECTuser_idFROMuserWHEREstatus1UNIONSELECTuser_idFROMapp_keyWHEREstatus1;-- UNION ALL仅简单纵向拼接**不去重、不排序**SELECTuser_idFROMuserWHEREstatus1UNIONALLSELECTuser_idFROMapp_keyWHEREstatus1;很多人踩坑以为 UNION UNION ALL二者性能差距极大。UNION UNION ALL DISTINCT 排序操作二、底层实现原理对比DISTINCT 原理在结果集内部构建临时内存哈希表或者排序缓冲区遍历数据消除本行内重复记录。数据量较小使用内存数据量大超过缓冲区限制则落地磁盘临时文件性能断崖下跌。UNION 原理分别执行前后两条子查询使用UNION ALL把所有数据纵向汇总全局执行一次DISTINCT排序去重。简单公式UNION UNION ALL DISTINCT三、核心性能结论如果业务需要合并多条SQL结果并且去重可以使用UNION如果多条SQL合并原始数据不存在重复优先使用UNION ALL不要用 UNION如果只是单表/单条查询内部去重不要使用 UNION直接使用DISTINCT杜绝滥用 UNION 实现单条SQL内部去重属于完全错误用法。四、场景分类实战分析场景1单条查询内部去除重复数据 ✅ DISTINCT需求查询当日登录日志里所有活跃用户ID同一用户多条登录记录只展示一次。-- 正确写法SELECTDISTINCTuser_idFROMuser_login_logWHEREdateCURDATE();-- ❌ 错误示范没必要强行拆分UNIONSELECTuser_idFROMuser_login_logWHEREdateCURDATE()UNIONSELECTuser_idFROMuser_login_logWHEREdateCURDATE();强行使用UNION会执行两次相同查询扫描双倍数据额外执行全局去重资源翻倍浪费。场景2多条独立查询结果合并需要全局去重需求从用户表、密钥表两处查询user_id合并结果同一个user_id只保留一条。方案A UNIONSELECTuser_idFROMuserWHEREusernamedemoUNIONSELECTuser_idFROMapp_keyWHEREaccess_keydemo_key;方案B UNION ALL 外层DISTINCTSELECTDISTINCTuser_idFROM(SELECTuser_idFROMuserWHEREusernamedemoUNIONALLSELECTuser_idFROMapp_keyWHEREaccess_keydemo_key)t;重点方案A 和方案B哪个更快绝大多数情况下UNION ALL 外层DISTINCT 性能 ≥ UNION原因UNION默认会附带排序行为而外层DISTINCT优化器可以选择哈希去重不一定强制排序优化空间更大。追求稳定高性能推荐统一使用UNION ALL DISTINCT写法避免UNION隐性排序带来开销。场景3多条查询合并明确不存在重复数据✅ 直接使用UNION ALL不要使用UNION不要额外加DISTINCT省去全局比较、排序、去重的巨大开销。SELECTidFROMuserLIMIT100UNIONALLSELECTidFROMapp_keyLIMIT100;五、高频误区汇总误区1UNION 和 DISTINCT 可以随意互相替换❌ 不能替换。DISTINCT作用于单查询内部UNION作用于多条查询合并之后适用场景边界完全不同。误区2UNION去重性能优于 UNION ALL DISTINCT❌ 恰恰相反。UNION强制执行排序去重UNION ALL只做拼接把去重选择权交给外层优化器拥有更多优化策略。误区3少量数据随便写无所谓在测试环境少量数据看不出差距当结果集上万、十万级别UNION额外排序会直接引发慢查询线上极易爆出性能故障。误区4不知道UNION自带排序导致不必要的消耗MySQL UNION规范合并完成后会执行排序操作如果你不需要排序不要使用UNION。六、索引层面额外优化提示DISTINCT查询尽量建立覆盖索引避免大量回表-- 示例利用索引直接完成去重无需读取原始数据表CREATEINDEXidx_date_userONuser_login_log(date,user_id);UNION ALL拆分多条查询时每条子查询务必保证可以正常命中索引如果最终只需要获取第一条匹配记录可以每层子查询增加 LIMIT 实现短路查询减少扫描行数。七、选型决策清单线上直接套用仅单条SQL内部去重→ 使用DISTINCT多条SQL结果合并存在重复且需要去重→ 优先UNION ALL 外层DISTINCT多条SQL结果合并确认无重复→ 使用UNION ALL禁止单条查询场景强行拆分使用UNION做去重禁止能用UNION ALL的场景随意使用UNION八、验证手段使用EXPLAIN观察执行计划UNION通常能看到Using temporary; Using filesort临时表文件排序UNION ALL没有全局排序与临时表执行计划更加简洁总结一句话去重工具没有绝对好坏分清场景再选择能使用 UNION ALL 就不要使用 UNION能避免全局排序就尽量避免。延伸业务小案例你项目常用场景根据账号、邮箱、密钥多条件检索用户ID-- 最优写法SELECTDISTINCTuser_idFROM(SELECTuser_idFROMuserWHEREusernamedemoUNIONALLSELECTuser_idFROMuserWHEREemaildemotest.comUNIONALLSELECTuser_idFROMapp_keyWHEREaccess_keydemo_key)tmp;相比直接写三条UNION性能更好也是线上检索场景标准写法。

相关新闻

最新新闻

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现 【免费下载链接】serenity The Serenity Operating System 🐞 项目地址: https://gitcode.com/GitHub_Trending/se/serenity 导读 本文以 getopt(3) 手册 为核心&a…

2026/10/1 19:32:24
轻量服务器还是ECS?大促云服务器选购与避坑实战指南

轻量服务器还是ECS?大促云服务器选购与避坑实战指南

每年大促节点,群里永远有人在问同一个问题:“38元的轻量服务器到底怎么抢?为什么我每次点进去都是已售罄?68元直购和99元的ECS我到底选哪个?”作为一个常年帮团队和自己采购云服务器的老用户,我太清楚这种纠…

2026/9/30 21:32:07
为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南 【免费下载链接】agents Multi-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity 项目地址:…

2026/9/30 19:41:56
PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署 【免费下载链接】PaddleOCR Turn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between i…

2026/10/1 19:32:23
Spring源码解析:构造器注入的类型转换与候选匹配机制

Spring源码解析:构造器注入的类型转换与候选匹配机制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 19:32:35
openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由 【免费下载链接】openai-agents-python A lightweight, powerful framework for multi-agent workflows 项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-pyth…

2026/9/30 21:32:11

日新闻

周新闻

月新闻