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

Mysql--基础知识点--94.1--嵌套子查询转关联查询

什么是嵌套子查询?为什么要改成关联查询?

嵌套子查询(Non-correlated subquery)是指子查询独立于外层查询,不引用外层的列。它先执行子查询得到结果集,然后外层查询利用这个结果集进行过滤或计算。

关联子查询(Correlated subquery)是指子查询引用了外层查询的列,对外层每一行都要执行一次子查询(通常可以利用索引快速判断)。

在某些场景下,将嵌套子查询改写成关联查询(如EXISTSJOIN)可以大幅提升性能,避免子查询产生巨大的中间结果集,或者避免NULL带来的逻辑陷阱。


典型改写场景:INEXISTS

原始嵌套子查询(使用IN

-- 找出所有下过至少一单的客户SELECT*FROMcustomersWHEREcustomer_idIN(SELECTcustomer_idFROMorders-- 子查询独立,不依赖外层);

执行逻辑

  1. 先完整执行子查询:从orders表中取出所有customer_id,可能几十万行。
  2. 将结果集去重并构建哈希表。
  3. customers每一行检查customer_id是否在哈希表中。

问题:如果orders表非常大(几百万行),子查询结果集巨大,会消耗大量内存和 I/O。

改写为关联查询(使用EXISTS

SELECT*FROMcustomers cWHEREEXISTS(SELECT1FROMorders oWHEREo.customer_id=c.customer_id-- 关联条件);

执行逻辑(实际优化器会做半连接):

  1. 遍历customers表(假设只有几千行)。
  2. 对每个客户,在orders表的索引上快速查找是否存在该客户的订单,找到一行就立即返回TRUE,不再继续扫描。
  3. 整个过程无需物化庞大的订单 ID 集合。

优势

  • 外表小、内表大时,EXISTS通常远快于IN
  • 避免了大结果集的物化,内存压力小。
  • 可以利用orders.customer_id上的索引。

另一种改写:嵌套子查询 →JOIN(关联查询)

-- 同样查询有订单的客户,使用 JOIN(注意去重)SELECTDISTINCTc.*FROMcustomers cJOINorders oONc.customer_id=o.customer_id;

注意JOIN可能导致客户重复(一个客户有多笔订单),所以需要DISTINCT。如果customers.customer_id是主键,DISTINCT的开销通常可接受。

性能特点

  • 数据库优化器可能将INEXISTS转换为类似的JOIN执行计划。
  • 但显式JOIN有时更灵活,可以同时获取订单表的其他字段。

什么时候不应该改写?

  • 子查询结果集很小(如几十行)且不经常执行:IN写法更直观,性能差异可忽略。
  • 需要判断NOT IN且子查询无NULL:但最好还是用NOT EXISTSLEFT JOIN避免NULL陷阱。
  • 子查询是标量查询(返回单个值),例如SELECT ... WHERE salary > (SELECT AVG(salary) FROM employees),这种无法简单改成关联查询,因为子查询只需执行一次。

总结对照表

写法子查询类型执行次数适用场景
IN (SELECT ...)嵌套(非关联)子查询执行1次子查询结果集小,且外表大
EXISTS (SELECT ... WHERE 关联)关联外表每行执行1次(但可提前终止)外表小,内表大,且内表有索引
JOIN ... ON 关联关联一次连接操作需要同时获取两表数据,注意去重

核心建议

  • 默认优先考虑语义清晰,但遇到性能问题时,把嵌套子查询(特别是INNOT IN)改写成关联查询(EXISTSJOIN)是非常有效的优化手段。
  • 使用EXPLAIN观察执行计划,确认数据库是否自动做了优化。
http://www.jsqmd.com/news/616194/

相关文章:

  • 2026年知名的威海大学生穷游住宿酒店大众好评榜 - 行业平台推荐
  • CodeMagicianT簿
  • MMDetection的学习笔记
  • 【算法日记 09】蓝桥杯实战:突破整数极限,拥抱“字符串思维”
  • Win10 停更、Win11 臃肿?试试这款精简win11系统,老电脑也能快到飞起,完整安装指南:手把手教你下载
  • 深度排查:Hyper-V 已关但 VirtualBox 仍报错的完整解决方案
  • OSCPRepo单词列表与密码字典:全面渗透测试资源清单
  • 2026苏稽跷脚牛肉top名录:苏稽跷脚牛肉最出名的牌子推荐/乐山苏稽古镇附近跷脚牛肉推荐/乐山苏稽特色推荐榜/选择指南 - 优质品牌商家
  • 终极ytdl-sub订阅配置教程:打造完美媒体库的完整解决方案
  • 电子书管理神器:OpenClaw+千问3.5-27B自动分类Calibre书库
  • 2026北京灭火器回收技术全解析:合规与环保双达标 - 优质品牌商家
  • Specs扩展开发指南:如何自定义存储类型和系统行为
  • 分享一个网络智能运维系统
  • 2026年热门的性价比高的酒店本地推荐 - 行业平台推荐
  • 从零搭建PHP智能校验系统:TensorFlow Lite轻量模型+PHP-Parser AST分析+实时反馈看板(完整Docker化部署手册)
  • sqlite_orm完全指南:现代C++中最强大的轻量级ORM库
  • OpenClaw模型微调指南:优化Qwen2.5-VL-7B特定场景图文识别准确率
  • 模型微调实战:让gemma-3-12b-it更好适配OpenClaw的自动化需求
  • 15DaysofAnimationsinSwift GIF动画播放:在iOS应用中集成动态图像
  • Linux内核中的网络协议栈详解
  • HarvestText情感分析:构建领域专属情感词典的完整流程
  • LexikJWTAuthenticationBundle源码解析:深入理解JWT认证实现原理
  • 数字生成器(骰子模拟器)
  • postgresql 常用函数,记录点滴
  • 2026Q2乐山苏稽跷脚牛肉选店指南:从食材到文化全解析 - 优质品牌商家
  • 10个echarts-gl性能优化技巧:WebGL加速和大型数据集处理终极指南
  • Windows下OpenClaw安装指南:对接Qwen2.5-VL-7B图文模型
  • 2026船闸网站推荐榜:三家行业标杆企业实力盘点 - 优质品牌商家
  • JavaScript中函数节流Throttle在滚动事件中的应用
  • mutt-wizard疑难排解终极指南:常见错误与解决方案完全清单