MySQL 两表集合运算性能对比:UNION ALL vs JOIN vs NOT IN 的 5 种场景实测
MySQL 两表集合运算性能对比UNION ALL vs JOIN vs NOT IN 的 5 种场景实测在数据库操作中集合运算是最基础也是最常用的功能之一。无论是数据报表生成、数据分析还是日常的业务查询我们经常需要对两个表进行并集、交集或差集运算。MySQL 提供了多种实现这些集合运算的方式包括UNION ALL、JOIN和NOT IN等。不同的实现方式在性能上可能有显著差异特别是在处理大数据量时。本文将基于 5 种典型场景对比这些集合运算方式的性能表现。我们将从执行计划、资源消耗和适用边界等多个维度进行分析帮助你在实际工作中做出更优的选择。1. 测试环境准备在开始性能对比之前我们需要先搭建测试环境。本次测试使用 MySQL 8.0.31硬件配置为 4 核 CPU 和 16GB 内存。我们创建两个表object_a和object_b结构如下CREATE TABLE object_a ( id bigint(20) NOT NULL AUTO_INCREMENT, oname varchar(50) DEFAULT NULL, odesc varchar(50) DEFAULT NULL, create_time datetime DEFAULT NULL, PRIMARY KEY (id), KEY idx_oname (oname), KEY idx_odesc (odesc) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE object_b ( id bigint(20) NOT NULL AUTO_INCREMENT, oname varchar(50) DEFAULT NULL, odesc varchar(50) DEFAULT NULL, create_time datetime DEFAULT NULL, PRIMARY KEY (id), KEY idx_oname (oname), KEY idx_odesc (odesc) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;我们准备了三种数据量级的测试数据小数据量每表 1,000 行中等数据量每表 10,000 行大数据量每表 100,000 行提示所有测试都在相同环境下进行每次测试前都会重启 MySQL 服务以确保结果不受缓存影响。2. 并集运算性能对比并集运算是最常见的集合操作之一MySQL 提供了UNION和UNION ALL两种方式来实现。2.1 UNION ALL 实现UNION ALL是最简单的并集实现方式它直接将两个查询结果合并不进行去重SELECT oname, odesc FROM object_a UNION ALL SELECT oname, odesc FROM object_b;2.2 UNION 实现UNION会在合并结果后进行去重操作SELECT oname, odesc FROM object_a UNION SELECT oname, odesc FROM object_b;2.3 性能对比我们对比了三种数据量下的执行时间单位毫秒数据量UNION ALLUNION1,000124510,00085420100,0009205,800从结果可以看出UNION ALL的性能明显优于UNION随着数据量增加UNION的额外去重操作带来的性能损耗更加明显注意如果确定两个表的数据没有重复或者业务允许结果中存在重复数据应优先使用UNION ALL。3. 交集运算性能对比MySQL 没有直接提供INTERSECT操作符但我们可以通过多种方式实现交集运算。3.1 INNER JOIN 实现最常用的交集实现方式是INNER JOINSELECT a.oname, a.odesc FROM object_a a INNER JOIN object_b b ON a.oname b.oname AND a.odesc b.odesc;3.2 IN 子查询实现也可以使用IN子查询实现交集SELECT oname, odesc FROM object_a WHERE (oname, odesc) IN (SELECT oname, odesc FROM object_b);3.3 EXISTS 实现EXISTS是另一种实现方式SELECT a.oname, a.odesc FROM object_a a WHERE EXISTS ( SELECT 1 FROM object_b b WHERE a.oname b.oname AND a.odesc b.odesc );3.4 性能对比三种实现方式的执行时间对比单位毫秒数据量INNER JOININ 子查询EXISTS1,00018322810,000120450380100,0001,5006,2005,800分析结论INNER JOIN在三种方式中性能最优IN和EXISTS性能相近但都比JOIN差数据量越大性能差异越明显4. 差集运算性能对比差集运算A - B表示在 A 中存在但在 B 中不存在的记录。MySQL 同样没有直接提供差集操作符但有多种实现方式。4.1 LEFT JOIN IS NULL 实现这是最常用的差集实现方式SELECT a.oname, a.odesc FROM object_a a LEFT JOIN object_b b ON a.oname b.oname AND a.odesc b.odesc WHERE b.id IS NULL;4.2 NOT IN 实现使用NOT IN也可以实现差集SELECT oname, odesc FROM object_a WHERE (oname, odesc) NOT IN (SELECT oname, odesc FROM object_b);4.3 NOT EXISTS 实现NOT EXISTS是另一种选择SELECT a.oname, a.odesc FROM object_a a WHERE NOT EXISTS ( SELECT 1 FROM object_b b WHERE a.oname b.oname AND a.odesc b.odesc );4.4 性能对比三种差集实现方式的执行时间单位毫秒数据量LEFT JOINNOT INNOT EXISTS1,00022353010,000180600520100,0002,1008,5007,800性能分析LEFT JOIN性能最优NOT EXISTS略优于NOT IN对于大数据量LEFT JOIN的优势更加明显5. 索引对性能的影响索引对集合运算的性能有重大影响。我们以交集运算为例测试了有无索引时的性能差异。5.1 有索引时的性能使用oname和odesc上的索引-- 确保索引存在 ALTER TABLE object_a ADD INDEX idx_oname_odesc(oname, odesc); ALTER TABLE object_b ADD INDEX idx_oname_odesc(oname, odesc); -- 测试查询 SELECT a.oname, a.odesc FROM object_a a INNER JOIN object_b b ON a.oname b.oname AND a.odesc b.odesc;5.2 无索引时的性能移除相关索引后测试-- 移除索引 ALTER TABLE object_a DROP INDEX idx_oname_odesc; ALTER TABLE object_b DROP INDEX idx_oname_odesc; -- 同样查询 SELECT a.oname, a.odesc FROM object_a a INNER JOIN object_b b ON a.oname b.oname AND a.odesc b.odesc;5.3 性能对比100,000 行数据时的执行时间单位毫秒场景执行时间有复合索引1,500无索引28,000关键发现合适的索引可以将查询性能提升一个数量级。对于频繁使用的集合运算字段建立适当的索引是必要的。6. 执行计划深度分析理解 MySQL 的执行计划对于优化查询至关重要。我们以差集运算为例分析不同实现方式的执行计划差异。6.1 LEFT JOIN 执行计划EXPLAIN SELECT a.oname, a.odesc FROM object_a a LEFT JOIN object_b b ON a.oname b.oname AND a.odesc b.odesc WHERE b.id IS NULL;典型执行计划对object_a进行全表扫描对object_b使用索引查找使用NULL条件过滤结果6.2 NOT EXISTS 执行计划EXPLAIN SELECT a.oname, a.odesc FROM object_a a WHERE NOT EXISTS ( SELECT 1 FROM object_b b WHERE a.oname b.oname AND a.odesc b.odesc );典型执行计划对object_a进行全表扫描对每行数据执行子查询子查询使用索引查找6.3 执行计划对比指标LEFT JOINNOT EXISTS扫描方式全表扫描全表扫描连接方式嵌套循环连接相关子查询索引使用连接条件使用索引子查询使用索引临时表可能使用不使用排序可能使用不使用从执行计划来看LEFT JOIN通常更高效因为它可以更好地利用索引并减少重复计算。7. 内存和 CPU 资源消耗除了执行时间我们还监控了不同集合运算方式对系统资源的消耗。7.1 内存使用对比使用SHOW STATUS LIKE Handler%监控内存操作操作方式内存临时表大小磁盘临时表使用UNION ALL低无UNION高大数据量时有INNER JOIN中等无LEFT JOIN中等无NOT IN高大数据量时有7.2 CPU 使用率对比使用SHOW PROFILE分析 CPU 使用操作方式CPU 使用率UNION ALL低UNION高INNER JOIN中等NOT EXISTS高提示UNION和NOT IN在高数据量时可能使用磁盘临时表这会显著降低性能并增加 I/O 压力。8. 实际应用建议基于以上测试结果我们总结出以下实践建议并集运算优先使用UNION ALL除非确实需要去重对于大数据量UNION考虑先分别对两个结果集去重再合并交集运算首选INNER JOIN性能最好确保连接条件字段有合适索引差集运算使用LEFT JOIN ... WHERE b.key IS NULL模式避免在大数据量时使用NOT IN通用优化建议为集合运算涉及的字段创建复合索引限制结果集大小避免返回过多数据考虑使用覆盖索引减少回表操作-- 覆盖索引示例 ALTER TABLE object_a ADD INDEX idx_covering(oname, odesc, id); ALTER TABLE object_b ADD INDEX idx_covering(oname, odesc, id);9. 特殊情况处理在实际应用中我们还会遇到一些特殊情况需要特别处理。9.1 NULL 值处理集合运算中的 NULL 值可能导致意外结果-- 此查询可能返回不符合预期的结果因为 NULL 的比较结果未知 SELECT a.oname, a.odesc FROM object_a a WHERE (oname, odesc) NOT IN (SELECT oname, odesc FROM object_b);解决方案使用IS NULL明确处理 NULL 值或者在表设计时避免允许 NULL 值9.2 大数据量分页对于大数据量的集合运算结果分页-- 低效做法全量排序后再分页 SELECT * FROM ( SELECT oname, odesc FROM object_a UNION ALL SELECT oname, odesc FROM object_b ) t ORDER BY oname LIMIT 10000, 20; -- 更高效做法分别排序后合并 (SELECT oname, odesc FROM object_a ORDER BY oname LIMIT 10020) UNION ALL (SELECT oname, odesc FROM object_b ORDER BY oname LIMIT 10020) ORDER BY oname LIMIT 10000, 20;9.3 多表复杂集合运算对于多个表的复杂集合运算可以分步进行-- 先计算 A 和 B 的交集 CREATE TEMPORARY TABLE temp_ab AS SELECT a.oname, a.odesc FROM object_a a INNER JOIN object_b b ON a.oname b.oname AND a.odesc b.odesc; -- 再计算与 C 的差集 SELECT ab.oname, ab.odesc FROM temp_ab ab LEFT JOIN object_c c ON ab.oname c.oname AND ab.odesc c.odesc WHERE c.id IS NULL;10. MySQL 8.0 新特性MySQL 8.0 引入了对标准 SQL 集合操作符的支持包括INTERSECT和EXCEPT-- 交集 TABLE object_a INTERSECT TABLE object_b; -- 差集 TABLE object_a EXCEPT TABLE object_b;这些新操作符语法更简洁直观默认进行去重操作可使用ALL保留重复项性能与传统的JOIN实现相当注意这些特性需要 MySQL 8.0.31 或更高版本。如果使用较旧版本仍需使用前面介绍的传统实现方式。

相关新闻

3大核心功能深度解析:YAAW-for-Chrome如何重塑你的Chrome下载体验

3大核心功能深度解析:YAAW-for-Chrome如何重塑你的Chrome下载体验

3大核心功能深度解析:YAAW-for-Chrome如何重塑你的Chrome下载体验 【免费下载链接】YAAW-for-Chrome Yet Another Aria2 Web Frontend in pure HTML/CSS/Javascirpt Powered by Chrome 项目地址: https://gitcode.com/gh_mirrors/ya/YAAW-for-Chrome YAAW-fo…

2026/7/6 21:47:27阅读更多 →
ResNet-50 特征图可视化:从Grad-CAM到3D卷积核的5步调试法

ResNet-50 特征图可视化:从Grad-CAM到3D卷积核的5步调试法

ResNet-50特征图可视化:5步诊断模型性能瓶颈的工程实践当你的ResNet-50模型在测试集上表现不佳时,作为工程师的你首先会做什么?调整超参数?增加数据量?这些常规操作可能让你在黑暗中摸索数周却收效甚微。本文将揭示一种…

2026/7/6 21:42:27阅读更多 →
Tampermonkey v4.19 + U校园脚本:浏览器自动化答题与挂时长配置 3 步指南

Tampermonkey v4.19 + U校园脚本:浏览器自动化答题与挂时长配置 3 步指南

Tampermonkey进阶实战:浏览器自动化工具的安全配置与高效管理在数字化学习环境中,效率工具正逐渐成为学生群体的得力助手。Tampermonkey作为最受欢迎的浏览器脚本管理工具之一,其灵活性和强大功能使其在自动化任务处理领域占据重要地位。本文…

2026/7/6 21:42:27阅读更多 →
Fusion Pixel Font像素字体终极指南:如何为你的项目注入复古灵魂

Fusion Pixel Font像素字体终极指南:如何为你的项目注入复古灵魂

Fusion Pixel Font像素字体终极指南:如何为你的项目注入复古灵魂 【免费下载链接】fusion-pixel-font 开源的泛中日韩像素字体,黑体风格 项目地址: https://gitcode.com/gh_mirrors/fu/fusion-pixel-font 想要为你的数字项目注入独特的复古像素美…

2026/7/6 22:52:36阅读更多 →
从零掌握OpenAI Codex:AI编程助手实战指南与API调用详解

从零掌握OpenAI Codex:AI编程助手实战指南与API调用详解

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 你好,我是专注于技术实战分享的博主。在探索AI辅助编程工具时,你是否遇到过这样的困境:面对一个复…

2026/7/6 22:52:36阅读更多 →
Diazo XSLT规则编写核心原理与实战避坑指南

Diazo XSLT规则编写核心原理与实战避坑指南

1. 项目概述:Diazo里XSLT不是“配角”,而是规则引擎的神经中枢在Plone这类老牌企业级CMS生态中,Diazo曾是前端主题化方案的事实标准——它用一种近乎优雅的方式,把后端生成的HTML和前端设计师交付的静态模板“缝合”在一起。而XSL…

2026/7/6 22:52:36阅读更多 →
操作系统内核实战:编写一个简易字符设备驱动(Linux 6.x + QEMU)

操作系统内核实战:编写一个简易字符设备驱动(Linux 6.x + QEMU)

操作系统内核实战:编写一个简易字符设备驱动(Linux 6.x QEMU)在计算机科学领域,操作系统内核是最神秘而又最核心的组件。它像一位不知疲倦的调度员,默默协调着硬件资源与软件请求之间的复杂交互。今天,我们…

2026/7/6 22:52:36阅读更多 →
IIM-42652 IMU与STM32L442KC的6DoF运动跟踪方案

IIM-42652 IMU与STM32L442KC的6DoF运动跟踪方案

1. IIM-42652 IMU传感器深度解析 IIM-42652是TDK旗下InvenSense品牌推出的一款6轴工业级MEMS运动跟踪设备,专为工业应用场景优化设计。这款仅有2.53.00.91mm尺寸的微型传感器,集成了三轴陀螺仪和三轴加速度计,采用LGA封装,支持I2C…

2026/7/6 22:52:36阅读更多 →
AI编程助手安全监控:本地审计工具Gryph的设计与实现

AI编程助手安全监控:本地审计工具Gryph的设计与实现

1. 项目概述:为什么我们需要一个AI编程助手的“行车记录仪”?最近几个月,我身边几乎所有搞开发的朋友,桌面右下角都多了一个AI编程助手的图标。从Copilot到Cursor,再到各种本地部署的大模型工具,它们确实能…

2026/7/6 22:47:35阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/6 4:26:20阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/6 2:48:33阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/6 0:10:35阅读更多 →
Seraphine:基于LCU API的英雄联盟智能游戏助手技术解析与应用指南

Seraphine:基于LCU API的英雄联盟智能游戏助手技术解析与应用指南

Seraphine:基于LCU API的英雄联盟智能游戏助手技术解析与应用指南 【免费下载链接】Seraphine 英雄联盟战绩查询工具 项目地址: https://gitcode.com/gh_mirrors/se/Seraphine 技术架构先行:官方接口的合规应用 你是否曾在BP阶段手忙脚乱&#x…

2026/7/6 0:03:39阅读更多 →
多协议远程连接管理工具mRemoteNG:告别混乱,统一你的远程桌面管理

多协议远程连接管理工具mRemoteNG:告别混乱,统一你的远程桌面管理

多协议远程连接管理工具mRemoteNG:告别混乱,统一你的远程桌面管理 【免费下载链接】mRemoteNG mRemoteNG is the next generation of mRemote, open source, tabbed, multi-protocol, remote connections manager. 项目地址: https://gitcode.com/gh_m…

2026/7/6 0:03:39阅读更多 →
COUNT(DISTINCT) 与 GROUP BY 去重统计:5 亿数据量下的性能实测与选型指南

COUNT(DISTINCT) 与 GROUP BY 去重统计:5 亿数据量下的性能实测与选型指南

COUNT(DISTINCT) 与 GROUP BY 去重统计:5 亿数据量下的性能实测与选型指南在数据分析和处理领域,去重统计是最基础也是最频繁使用的操作之一。当数据量达到亿级规模时,不同的去重统计方法在性能上可能产生天壤之别。本文将基于 5 亿行数据的实…

2026/7/6 0:03:39阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/6 4:45:01阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/6 4:45:01阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/6 4:45:03阅读更多 →