当前位置: 首页 > article >正文

SQL查询优化:NOT EXISTS与LEFT JOIN性能对比

NOT EXISTS和LEFT JOIN...IS NULL在逻辑上等价但性能差异显著。NOT EXISTS采用半连接(Semi Join)机制找到第一个匹配即停止扫描内存占用低LEFT JOIN则需完成全连接后再过滤内存消耗高。在users表100万行、orders表1亿行的场景下NOT EXISTS执行更快成本800 vs 5000。最佳实践建议优先使用NOT EXISTS尤其当子表数据量大或查询列可能含NULL时通过执行计划验证关注NESTED LOOPS ANTI和INDEX RANGE SCAN等高效操作符确保子查询连接列建立索引。真实案例显示NOT EXISTS将8小时的查询优化至45秒完成。NOT EXISTS 和 LEFT JOIN ... IS NULL 在性能上的细微差别以及如何通过执行计划来判断哪个更优NOT EXISTS和LEFT JOIN ... IS NULL在逻辑上等价但在执行计划上可能有天壤之别。理解它们的差异是 SQL 优化的高级技能。我用一个经典场景来说明查找没有订单的用户。sql-- 方法1: NOT EXISTS SELECT u.* FROM users u WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id u.user_id); -- 方法2: LEFT JOIN ... IS NULL SELECT u.* FROM users u LEFT JOIN orders o ON u.user_id o.user_id WHERE o.user_id IS NULL;一、核心性能差异对比表对比维度NOT EXISTSLEFT JOIN ... IS NULL执行逻辑半连接 (Semi Join)找到第一个匹配行就停止反连接 (Anti Join)完成全部连接后再过滤扫描行为短路的对每个用户找到一张订单立即停止非短路的必须找出用户的所有订单才能确定是否匹配内存使用低哈希表较小通常只存连接键高需要构建完整哈希表用于检测匹配NULL 处理天然正确子查询不返回 NULL依赖IS NULL过滤逻辑正确但额外开销优化器倾向现代优化器通常能转换为 ANTI JOIN但仍有差异强制产生 ANTI JOIN缺少短路径二、为什么不同深度原理剖析1. NOT EXISTS 的短路特性sql-- 伪代码示例 NOT EXISTS 的逻辑 for each user in users: index_lookup on orders.user_id user.id if no order found: -- 只要没找到订单立即输出用户 output user关键某个用户如果有 1000 个订单NOT EXISTS 在找到第 1 个订单后就停止扫描该用户的订单转向下一个用户。2. LEFT JOIN ... IS NULL 的全连接特性sql-- 伪代码示例 LEFT JOIN 的逻辑 hash_table build_hash_index(orders.user_id); -- 必须先构建所有订单的哈希表 for each user in users: look up in hash_table if match found: mark as matched output (user, matched_flag) -- 最终过滤出 matched_flag NULL 的记录关键必须完成所有用户的完整连接才能在最后一步过滤出IS NULL的记录。即使某个用户有 1000 个订单也要全部连接完虽然哈希表能快速判断存在但无法提前短路。三、性能差异的具体场景场景NOT EXISTSLEFT JOIN ... IS NULL结论users: 100万, orders: 1亿 (大多有订单)✅快能快速短路❌慢需要构建大哈希表NOT EXISTS 完胜users: 100万, orders: 1000 (只有少数有订单)✅快找不到订单立即输出⚠️可接受哈希表小NOT EXISTS 略优users: 100万, orders: 0⚠️一般找不到订单需检查每个用户⚠️一般哈希表为空但需扫描全表性能相近子查询列允许 NULL✅安全不受影响❌危险逻辑可能出错NOT EXISTS 更安全四、如何看懂执行计划1. 在 Oracle 中查看执行计划sql-- 开启执行计划跟踪 SET AUTOTRACE TRACEONLY EXPLAIN; -- 或使用 DBMS_XPLAN EXPLAIN PLAN FOR SELECT u.* FROM users u WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id u.user_id); SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);2. 关键操作符识别执行计划中的操作符含义代表查询类型性能HASH ANTI JOIN哈希反连接LEFT JOIN ... IS NULL内存消耗高MERGE ANTI JOIN归并反连接LEFT JOIN ... IS NULL需要排序NESTED LOOPS ANTI JOIN嵌套循环反连接NOT EXISTS (优化良好)适合小驱动集FILTER (NOT EXISTS)过滤操作符NOT EXISTS (传统方式)可能慢逐行执行INDEX SKIP SCAN索引跳跃扫描用于反连接优化中等3. 实战解析两个执行计划场景users 表 10 万行orders 表 1000 万行user_id 列都有索引。执行计划 ALEFT JOIN ... IS NULLtext------------------------------------------------------------ | Id | Operation | Name | Rows | Cost | ------------------------------------------------------------ | 0 | SELECT STATEMENT | | 50000 | 5000 | | 1 | FILTER | | | | |* 2 | HASH JOIN ANTI | | 50000 | 5000 | | 3 | TABLE ACCESS FULL| USERS | 100K | 100 | | 4 | TABLE ACCESS FULL| ORDERS | 10M | 4000 | ------------------------------------------------------------解读HASH JOIN ANTI进行了反连接将两张表都全表扫描构建哈希表Cost 高5000问题内存中构建了 10M 行的 orders 哈希表内存压力大10万次探测执行计划 BNOT EXISTStext------------------------------------------------------------- | Id | Operation | Name | Rows | Cost | ------------------------------------------------------------- | 0 | SELECT STATEMENT | | 50000 | 800 | | 1 | NESTED LOOPS ANTI | | 50000 | 800 | | 2 | TABLE ACCESS FULL | USERS | 100K | 100 | |* 3 | INDEX RANGE SCAN | IDX_ORDERS| 1 | 7 | -------------------------------------------------------------解读NESTED LOOPS ANTI嵌套循环反连接外部表是 USERS关键对每个用户只做一次INDEX RANGE SCAN扫描 orders 的 user_id 索引找到第一个匹配即停Cost 低800快 6 倍以上优势不扫描全表 orders内存占用极低五、优劣判断速查表判断标准NOT EXISTS 什么时候更好LEFT JOIN 什么时候更好被驱动表orders非常大✅更好避免大表扫描❌更差必须扫描或哈希大表被驱动表orders非常小⚠️ 差不多⚠️ 差不多被驱动表允许 NULL✅安全❌危险可能逻辑错误驱动表users有选择性过滤✅更好只处理过滤后的用户⚠️ 一般需要返回多列✅ 都行✅ 都行数据库优化器较老✅更可靠❌ 可能优化失误六、最佳实践建议默认优先使用NOT EXISTS尤其在被驱动的子表非常大百万级以上主表经过 WHERE 过滤后结果集很小子查询列可能包含 NULL谨慎使用LEFT JOIN ... IS NULL仅在确认子查询列无 NULL需要返回主表的全部列且优化器对 NOT EXISTS 优化不佳时两种写法性能差异不大但你更习惯这种写法时通过执行计划验证sql-- 检查关键指标 -- ✅ 好计划NESTED LOOPS ANTI INDEX RANGE SCAN -- ❌ 坏计划HASH JOIN ANTI TABLE ACCESS FULL (大表) -- ❌ 坏计划FILTER (逐行执行子查询)索引策略sql-- NOT EXISTS 最佳索引在子查询的连接列上创建索引 CREATE INDEX idx_orders_user_id ON orders(user_id); -- 如果 orders 表经常做这种反连接查询考虑覆盖索引 CREATE INDEX idx_orders_cover ON orders(user_id, order_id);极端优化大表场景sql-- 使用物化视图或位图索引加速 NOT EXISTS CREATE BITMAP INDEX idx_orders_user_bitmap ON orders(user_id); -- 或在 Oracle 中使用 ANTI JOIN 提示 SELECT /* HASH_AJ(users orders) */ * FROM users u WHERE NOT EXISTS (...);七、一个真实案例生产环境某电商平台users: 500 万orders: 2 亿需求查找近 1 年无购买的用户sql-- 错误的方式执行了 8 小时内存溢出 SELECT u.* FROM users u LEFT JOIN orders o ON u.user_id o.user_id AND o.order_date SYSDATE - 365 WHERE o.user_id IS NULL; -- 正确的方式执行 45 秒 SELECT u.* FROM users u WHERE NOT EXISTS ( SELECT 1 FROM orders o WHERE o.user_id u.user_id AND o.order_date SYSDATE - 365 ); -- 更快的方案23 秒使用位图索引 SELECT u.* FROM users u WHERE u.user_id NOT IN (SELECT user_id FROM orders WHERE order_date SYSDATE - 365);结论对于大数据量反连接查询NOT EXISTS通常是首选但最佳实践是用执行计划证明而不是靠猜测。

相关文章:

SQL查询优化:NOT EXISTS与LEFT JOIN性能对比

NOT EXISTS和LEFT JOIN...IS NULL在逻辑上等价但性能差异显著。NOT EXISTS采用半连接(Semi Join)机制,找到第一个匹配即停止扫描,内存占用低;LEFT JOIN则需完成全连接后再过滤,内存消耗高。在users表100万行、orders表1亿行的场景…...

Oracle 常用数据类型:数值类型、字符类型、日期时间、大对象、特殊类型(ROWID、XML、JSON)附:和 MySql对比,Oracle 特有的关键字或方法

Oracle提供了丰富的数据类型,主要包括:数值类型:NUMBER为主,支持任意精度数值,FLOAT用于科学计算字符类型:VARCHAR2最常用,CHAR用于定长,CLOB处理大文本日期时间:DATE(最…...

自举电容如何提升MOSFET驱动电压

自举电容(Bootstrap Capacitor)是功率电子电路中一种特殊的储能元件,其核心功能是为高侧(High-Side)开关器件(通常是N沟道MOSFET)的栅极驱动器提供一个高于其源极电压的驱动电压,从而…...

如何高效地阅读技术文档?

如何高效地阅读技术文档? 技术文档是开发者日常工作中不可或缺的资源,但面对冗长复杂的文档,许多人常常感到无从下手。高效阅读技术文档不仅能节省时间,还能快速解决问题。那么,如何提升阅读效率呢?以下从…...

ClawTeam:AI代理协作框架,从单兵作战到群体智能的革命

1. 项目概述:从单兵作战到群体智能的AI代理协作革命如果你和我一样,长期在AI辅助编程和自动化领域摸爬滚打,那你一定经历过这样的场景:面对一个复杂的全栈项目,你让Claude Code或者Codex去实现,它吭哧吭哧写…...

开关电源工作原理

开关电源是一种通过控制功率开关器件(如MOSFET、IGBT)的导通与关断时间比率(占空比)来调节输出电压和功率的高效率电能变换装置。其核心是利用高频开关动作,配合储能元件(电感、电容)&#xff0…...

轻量级API网关Lunaroute:嵌入式设计与微服务流量治理实践

1. 项目概述:一个轻量级、高性能的API网关最近在梳理团队内部微服务架构的治理方案时,我又重新审视了API网关这个核心组件。市面上成熟的网关产品很多,像Kong、Tyk、APISIX等,功能强大,生态完善,但对于一些…...

麦橘超然Flux控制台实战:如何生成赛博朋克风格的高清图片

麦橘超然Flux控制台实战:如何生成赛博朋克风格的高清图片 1. 项目介绍与核心优势 麦橘超然Flux控制台是基于DiffSynth-Studio构建的离线图像生成Web服务,集成了majicflus_v1模型,通过float8量化技术显著降低了显存占用。这个解决方案特别适…...

浏览器工作原理从输入URL到页面渲染

当你在浏览器地址栏输入一个网址并按下回车时,短短几秒内,一个完整的网页就呈现在你眼前。这背后隐藏着一系列复杂而精妙的过程,涉及网络通信、数据解析和视觉渲染等多个环节。本文将带你深入探索浏览器从输入URL到页面渲染的工作原理&#x…...

为什么你的低代码应用在VSCode里“看不见”变量?深度解析Webview沙箱隔离、eval上下文丢失与Source Map v3兼容性危机

更多请点击: https://intelliparadigm.com 第一章:为什么你的低代码应用在VSCode里“看不见”变量? 当你在 VSCode 中打开一个由主流低代码平台(如 OutSystems、Mendix 或国内轻流、明道云)导出的前端项目时&#xff…...

LaserGRBL终极指南:如何快速上手开源激光雕刻控制软件

LaserGRBL终极指南:如何快速上手开源激光雕刻控制软件 【免费下载链接】LaserGRBL Laser optimized GUI for GRBL 项目地址: https://gitcode.com/gh_mirrors/la/LaserGRBL LaserGRBL是一款专为GRBL控制器优化的免费开源激光雕刻软件,为Windows用…...

微软RD-Agent:自动化AI研发框架,实现数据驱动的智能体协同进化

1. 项目概述:当AI开始驱动AI研发 如果你是一名数据科学家、量化研究员或者机器学习工程师,过去一年里,你肯定没少和各类AI助手打交道。从帮你写几行数据清洗代码,到解释一个复杂的模型原理,这些基于大语言模型的工具确…...

AstrBot主动聊天插件:赋予AI主动关怀能力的完整解决方案

1. 项目概述如果你用过AstrBot,或者玩过其他聊天机器人框架,大概率会有一个共同的感受:Bot总是被动的。它像一个永远在等待指令的助手,只有你主动它、问它,它才会回应。这种交互模式在初期很新鲜,但时间一长…...

Llama-3.2V-11B-cot 企业级应用:基于SpringBoot构建智能客服工单系统

Llama-3.2V-11B-cot 企业级应用:基于SpringBoot构建智能客服工单系统 每次看到客服同事在工单系统里,手动一张张点开用户上传的截图,费力地识别里面的错误代码或者产品瑕疵,然后复制粘贴、分类、写回复,我就觉得这事儿…...

Chord视频分析多场景落地:自动驾驶仿真视频中交通参与者行为预测标注

Chord视频分析多场景落地:自动驾驶仿真视频中交通参与者行为预测标注 1. 项目概述 Chord视频时空理解工具是基于Qwen2.5-VL架构开发的本地智能视频分析解决方案,专门针对视频时空定位与视觉深度理解场景设计。该工具在自动驾驶仿真视频分析领域具有重要…...

多智能体协作网络协议(ANP)设计:从消息格式到生产部署

1. 项目概述:从单体智能到协同网络的范式跃迁最近在开源社区里,一个名为“AgentNetworkProtocol”的项目引起了我的注意。这个名字听起来有点宏大,但当你深入进去,会发现它触及了当前AI应用开发中一个非常核心且日益凸显的痛点&am…...

深度学习模型集成:堆叠泛化实战指南

1. 深度学习模型集成方法概述在机器学习实践中,单个模型的表现往往存在局限性。模型集成技术通过组合多个模型的预测结果,通常能够获得比单一模型更优的性能。其中,堆叠泛化(Stacking Generalization)是一种强大的集成…...

终极指南:如何用CXPatcher一键提升Mac上CrossOver游戏性能

终极指南:如何用CXPatcher一键提升Mac上CrossOver游戏性能 【免费下载链接】CXPatcher A patcher to upgrade Crossover dependencies and improve compatibility 项目地址: https://gitcode.com/gh_mirrors/cx/CXPatcher 还在为Mac上运行Windows游戏卡顿、闪…...

终极免费方案:如何在浏览器中快速查看Parquet文件?

终极免费方案:如何在浏览器中快速查看Parquet文件? 【免费下载链接】parquet-viewer View parquet files online 项目地址: https://gitcode.com/gh_mirrors/pa/parquet-viewer 还在为查看Parquet文件而烦恼吗?传统工具需要复杂安装、…...

茉莉花插件:3步解决Zotero中文文献管理的世纪难题

茉莉花插件:3步解决Zotero中文文献管理的世纪难题 【免费下载链接】jasminum A Zotero add-on to retrive CNKI meta data. 一个简单的Zotero 插件,用于识别中文元数据 项目地址: https://gitcode.com/gh_mirrors/ja/jasminum 如果你是一名中文科…...

上下文工程:让Agent真正用好记忆与知识

拥有记忆和检索能力,只是 Agent 智能化的第一步。如何在有限的上下文窗口内,高效地组织、筛选和利用这些信息,才是决定 Agent 实际表现的关键——这正是上下文工程(Context Engineering)所要解决的问题。 什么是上下文…...

建议收藏 | 构建长期运行 AI Agent 的 5 种核心设计模式!

在 AI 开发圈,有一个心照不宣的误区:只要 Prompt 写得够好,模型能力够强,Agent 就能在生产环境里大杀四方。 但在现实中,当你想让 Agent 帮公司处理几千份跨部门理赔,或者运行一个长达一周的自动化销售序列…...

CUDA 13内存模型重大变更(Unified Virtual Memory默认启用):GPU显存泄漏排查效率下降65%?一文掌握3种LLM训练场景下的精准定位法

更多请点击: https://intelliparadigm.com 第一章:CUDA 13内存模型演进与Unified Virtual Memory本质解析 CUDA 13 对统一虚拟内存(Unified Virtual Memory, UVM)进行了关键性增强,核心在于将 GPU 内存管理从显式分页…...

C++26反射元编程性能白皮书:基准测试显示编译时间降低41%,运行时开销趋近于零(含LLVM IR对比分析)

更多请点击: https://intelliparadigm.com 第一章:C26反射元编程的演进与核心价值 C26 正式将静态反射(static reflection)纳入核心语言特性,标志着元编程范式从模板元编程(TMP)和 constexpr 编…...

AI算子上线即崩?揭秘CUDA 13生产集群中93%隐性PTX兼容性故障的3层诊断法(含cuobjdump逆向校验脚本)

更多请点击: https://intelliparadigm.com 第一章:AI算子上线即崩?揭秘CUDA 13生产集群中93%隐性PTX兼容性故障的3层诊断法(含cuobjdump逆向校验脚本) 当AI算子在CUDA 13.2集群中突然触发cudaErrorInvalidPtx或静默降…...

嵌入式+PLC+微服务联合调试实战(VSCode工业调试全栈手册)

更多请点击: https://intelliparadigm.com 第一章:VSCode工业调试全景概览 VSCode 已成为现代工业级软件开发与嵌入式系统调试的事实标准前端工具,其通过可扩展的调试适配器协议(DAP)无缝集成 GDB、LLDB、OpenOCD、J…...

皮带轮零件机械加工工艺规程制订及工艺装备设计毕业设计(说明书+CAD图纸+SolidWorks图纸+其它相关资料)

在机械制造领域,皮带轮作为传动系统的核心零件,其加工质量直接影响设备运行的稳定性与效率。针对这一关键零件的机械加工工艺规程制订及工艺装备设计,需系统整合材料特性、加工精度要求、设备性能等多维度因素,形成一套科学、规范…...

Phi-3.5-mini-instruct惊艳案例:复杂嵌套JSON Schema生成与验证反馈闭环

Phi-3.5-mini-instruct惊艳案例:复杂嵌套JSON Schema生成与验证反馈闭环 1. 模型能力概览 Phi-3.5-mini-instruct是微软推出的轻量级开源指令微调大模型,在长上下文代码理解(RepoQA)和多语言MMLU等基准测试中表现优异。这款模型…...

AC-GAN原理与实践:实现类别可控的图像生成

1. 项目概述:理解AC-GAN的核心价值AC-GAN(Auxiliary Classifier GAN)是生成对抗网络家族中一个极具实用价值的变体。我第一次接触这个架构是在解决图像生成任务时,发现普通GAN生成的图像虽然质量不错,但无法精确控制生…...

Kandinsky-5.0-I2V-Lite-5s作品赏析:基于Matlab图像处理后的风格化视频生成

Kandinsky-5.0-I2V-Lite-5s作品赏析:基于Matlab图像处理后的风格化视频生成 1. 跨界融合的技术亮点 当科学计算遇上AI生成,会碰撞出怎样的火花?这次我们要展示的是Matlab图像处理与Kandinsky视频生成模型的创新组合。这种跨界合作让原本专业…...