一、核心概念定义
DEPENDENT SUBQUERY 即相关子查询,是 MySQL 子查询的核心类型之一,核心特性如下:
•子查询无法独立执行,必须依赖外层查询当前行的字段值;
•执行逻辑为逐行联动:外层查询每读取一行数据,子查询就会执行一次;
•对应普通子查询(SUBQUERY):仅执行1次,结果全局缓存,外层直接复用,无重复执行开销。
在 EXPLAIN 执行计划 中,子查询行的 select_type 字段显示为 DEPENDENT SUBQUERY,即可判定为相关子查询。
二、实战示例SQL
需求:查询每个部门中,薪资高于本部门平均薪资的员工信息
sql |
核心关联逻辑:子查询中 e1.dept_id 引用外层查询表字段,必须等待外层读取当前行数据后,才能执行子查询计算,因此形成依赖关系。
三、完整执行流程(流程图+步骤拆解)
3.1 可视化执行流程图
mermaid |
3.2 分步执行原理
1. 外层循环扫描:逐行读取外层表 e1 的数据,提取当前行的 dept_id 字段值;
2. 参数传递:将外层当前行的 dept_id 传入内层子查询,作为筛选条件;
3. 子查询单次执行:根据传入的部门ID,计算该部门的员工平均薪资;
4. 条件校验:对比当前员工薪资与部门平均薪资,筛选符合条件的数据;
5. 循环迭代:外层每切换一行数据,重复上述所有步骤,直至全表扫描完成。
核心性能痛点:外层表有 N 行数据,子查询就会执行 N 次,外层数据量越大,性能开销呈线性增长,无索引时极易出现性能雪崩。 |
四、具象数据演示
4.1 测试数据表(emp)
name(姓名) | salary(薪资) | dept_id(部门ID) |
张三 | 10000 | 10 |
李四 | 8000 | 10 |
王五 | 15000 | 20 |
赵六 | 12000 | 20 |
4.2 逐行执行过程
1. 外层读取【张三】(dept_id=10)→ 子查询计算10部门平均薪资=9000 → 10000>9000,保留数据;
2. 外层读取【李四】(dept_id=10)→ 子查询重新计算10部门平均薪资=9000 → 8000<9000,丢弃数据;
3. 外层读取【王五】(dept_id=20)→ 子查询计算20部门平均薪资=13500 → 15000>13500,保留数据;
4. 外层读取【赵六】(dept_id=20)→ 子查询重新计算20部门平均薪资=13500 → 12000<13500,丢弃数据。
本次测试外层共4行数据,子查询累计执行4次,充分体现相关子查询的执行特性。
五、相关子查询 VS 普通子查询(SUBQUERY)
5.1 普通子查询示例
sql |
5.2 核心区别对比
对比维度 | DEPENDENT SUBQUERY(相关子查询) | SUBQUERY(普通子查询) |
执行次数 | 外层N行,执行N次 | 仅执行1次 |
依赖关系 | 依赖外层当前行数据 | 独立执行,无外部依赖 |
结果缓存 | 无全局缓存,每次重新计算 | 结果全局缓存,全程复用 |
性能开销 | 大数据量下开销极高 | 开销极低 |
六、MySQL相关子查询性能问题与优化方案
6.1 常见性能坑点
•MySQL 旧版本中,IN+子查询 极易被优化为 DEPENDENT SUBQUERY,引发性能暴跌;
•EXISTS 语法底层会被优化为相关子查询,无索引时性能极差,有索引时可快速终止匹配,性能尚可;
•核心瓶颈:重复执行子查询,数据量越大,性能劣化越明显。
6.2 最优优化方案:改写为JOIN查询
将逐行执行的相关子查询,改写为一次性预计算+关联查询,彻底避免子查询重复执行。
sql |
优化核心优势:子查询仅执行1次,预计算所有部门平均薪资,后续仅做表关联匹配,时间复杂度从 O(N*M) 降至 O(N+M)。
七、总结
1. DEPENDENT SUBQUERY 本质是行级联动查询,子查询依赖外层行数据、循环执行;
2. 性能短板极其明显,仅适用于小数据量场景,生产环境需尽量规避;
3. 最优优化思路:用 JOIN 替代相关子查询,预计算聚合结果,消除循环执行开销;
4. 日常排查慢SQL时,EXPLAIN 结果中出现大量 DEPENDENT SUBQUERY,优先进行优化改写。
字里行间,幸得你驻足品读。我是昌哥,欢迎关注与留言,共赴一场思想的碰撞。
-----------------------END-----------------------
各大平台都可以找到我:
————————————————————————————
公众号:昌哥知识星球
技术博客:http://www.linuxmysql.com
墨天轮:https://www.modb.pro/u/427810
CSDN :https://blog.csdn.net/rscpass
51CTO: https://blog.51cto.com/u_16068254
博客园:https://home.cnblogs.com/u/rscpass
知乎:https://www.zhihu.com/people/shukuinfo
掘金:https://juejin.cn/user/2801995051703454
百家号:https://author.baidu.com/home/1780697309880431
作者:阮胜昌
拥有:MySQL8.0 OCP、Oracle OCP、TIDB PCTA/PCTP/PCSD、Kingbase KCP,软考中级数据库系统工程师、RHCE7.0等行业认证
擅长主流数据库MySQL、Oracle、PostgreSQL的备份恢复,SQL调优、监控运维、故障应急处理等
可提供的技术服务:
1.数据库故障处理/疑难杂症远程支援
2.MySQL/PG/Oracle/SQLSERVER数据库技术服务
欢迎关注我的博客:http://www.linuxmysql.com 一起学习新知识!
昌哥IT课堂 开启薪未来|昌哥赋能 实战无忧 联系方式:rscpass (微信)



昌哥IT课堂|运维良方MySQL DEPENDENT SUBQUERY(相关子查询)原理详解