为什么SQL非相关子查询执行计划只缓存一次,其执行结果如何被重用?
- 内容介绍
- 相关推荐
本文共计969个文字,预计阅读时间需要4分钟。
非相关子查询仅执行一次,并非语法规定,而是优化器主动进行的省事动作——它识别出子查询不依赖于外部数据,便将其结果一次性计算出,存储在内存中的常量区域或临时物化表中,后续重复使用。
怎么快速判断一个子查询是不是非相关的
核心就一条:子查询里有没有出现外层表的列名(比如 t1.id、orders.user_id)。
- 没有——就是非相关,例如
(SELECT MAX(price) FROM products)、(SELECT value FROM config WHERE key = 'timeout') - 有——就是相关,例如
(SELECT COUNT(*) FROM logs WHERE user_id = users.id),哪怕只多写了一个点号,也会触发逐行重算 - 验证方法:把子查询整段复制出来,单独
SELECT一把,能跑通且不报“Unknown column”就是非相关
EXPLAIN 里怎么看它到底执行了几次
不能只看 select_type 是 SUBQUERY 还是 DEPENDENT SUBQUERY,得结合执行计划结构来确认实际行为。
本文共计969个文字,预计阅读时间需要4分钟。
非相关子查询仅执行一次,并非语法规定,而是优化器主动进行的省事动作——它识别出子查询不依赖于外部数据,便将其结果一次性计算出,存储在内存中的常量区域或临时物化表中,后续重复使用。
怎么快速判断一个子查询是不是非相关的
核心就一条:子查询里有没有出现外层表的列名(比如 t1.id、orders.user_id)。
- 没有——就是非相关,例如
(SELECT MAX(price) FROM products)、(SELECT value FROM config WHERE key = 'timeout') - 有——就是相关,例如
(SELECT COUNT(*) FROM logs WHERE user_id = users.id),哪怕只多写了一个点号,也会触发逐行重算 - 验证方法:把子查询整段复制出来,单独
SELECT一把,能跑通且不报“Unknown column”就是非相关
EXPLAIN 里怎么看它到底执行了几次
不能只看 select_type 是 SUBQUERY 还是 DEPENDENT SUBQUERY,得结合执行计划结构来确认实际行为。

