【MySQL·8.0·源码】subquery 子查询处理分析(一)

引言

在 SQL 中,子查询属于 Nested Query 的一种形式,根据 Kim 的分类[1],Nested Query 即嵌套查询是一种 SQL-like 形式的查询语句嵌套在另一 SQL 中,SQL-like 的嵌套子句可以出现在 SELECT、FROM 和 WHERE 子句的任意位置。

在 MySQL 中,一般把出现在 WHERE 子句中的嵌套 SQL 称为 subquery(子查询),而出现在 FROM 子句的称为 derived table,因为出现在 WHERE 子句中,最终属于 boolean factor 的一部分,目的是为了进行 FILTER 过滤记录。而出现在 FROM 子句不同,其结果最终是需要以抽象成一张虚拟表,用以与其他表进行 JOIN 操作或者用于二次计算过滤使用。

subquery 出现在 WHERE 子句中,而谓词形式一般为 [Ri.ck op Q]:

Ri 表示为第 i 张 Relation,ck 表示第 k 列,op 表示运算操作符,Q 则表示一个 SQL-like 形式的子查询

op 可以是 scalar 标量比较运算符(=、!=、>、>=、<、<=)或者是 set 集合成员运算符(IS IN,IS NOT IN、EXISTS、NOT EXISTS、ANY、ALL、SOME)。
两者的区别在于 scalar 标量运算符的右操作数总是返回当行当列值,而 set 运算符右操作数则是一个集合。
例如:

  • scalar 子查询

    select * from t1 where c1 = (select max(c1) from t2 where c2 > 25);
    
  • 普通子查询

    select * from t1 where c1 in (select c1 from t2 where c2 > 25);
    

Rule-based 转换

前面在 【MySQL·8.0·源码】MySQL 的查询处理有介绍,SQL 在 Transform 阶段会根据规则进行尝试简化,在此之前,我们必须知道子查询有以下等效规则[2]:

  1. Exists 的转换
    WHERE EXISTS (select <sel> from <tbl> where <cond>)
    
    可以被等效为
    WHERE 0 < (select count(<sel>) from <tbl> where <cond>)
    
  2. Not Exists 的转换
    WHERE NOT EXISTS (select <sel> from <tbl> where <cond>)
    
    可以被等效为
    WHERE 0 = (select count(<sel>) from <tbl> where <cond>)
    
  3. ANY 和 ALL 的转换
  • < ANY
    < ANY (select <sel> from <tbl> where <cond>)
    
    可以被等效为
    < (select MAX(<sel>) from <tbl> where <cond>)
    
  • > ANY
    > ANY (select <sel> from <tbl> where <cond>)
    
    可以被等效为
    > (select MIN(<sel>) from <tbl> where <cond>)
    
  • < ALL
    < ALL (select <sel> from <tbl> where <cond>)
    
    可以被等效为
    < (select MIN(<sel>) from <tbl> where <cond>)
    
  • > ALL
    > ALL (select <sel> from <tbl> where <cond>)
    
    可以被等效为
    > (select MAX(<sel>) from <tbl> where <cond>)
    

语法树形式

引言中介绍了子查询有以下形式:

select <selitems> from Ri where Ri.ck op <Q>

在 【MySQL·8.0·源码】MySQL 语法树基础知识 中有介绍,在 MySQL 中,<SELECT><WHERE> 子句都是使用 Item 来表示各个 expression 表达式的。
对于子查询也不例外,MySQL 通过使用一个 Item_subselect 的基类引申不同类型的子查询:
Item_subselect 基类的继承关系有:

Item_subselect
+--Item_singlerow_subselect
   +--Item_maxmin_subselect
+--Item_exists_subselect
   +--Item_in_subselect
      +--Item_allany_subselect

其中:

  • Item_singlerow_subselect 对应的是 SCALAR 子查询或者单行的子查询
  • Item_exists_subselect 对应的是 [NOT] EXISTS 的子查询
  • Item_in_subselect 对应的是 [NOT] IN 子查询
  • Item_allany_subselect 对应 <op> ALL 或者 <op> ANY 形式的子查询

引言中提到,子查询是 Nested Query 的一种形式,在【MySQL·8.0·源码】MySQL 语法树结构 中有介绍过形如另外几种形式的嵌套查询:

  • 括号嵌套查询
select * from t3, (t1, t2) where t1.c1 = t2.c2;
  • 外连接嵌套查询
select * from t1 left outer join(t2, t3) on t1.c1 = t2.c1 and t1.c2 = t3.c2 where t1.c1 = t2.c2;

它们两的语法结构形式可以回顾【MySQL·8.0·源码】MySQL 语法树结构 。

同理,子查询作为另外一种嵌套查询,在 MySQL 中也是以相同的形式进行组织,而且子查询的 WHERE 子句上也使用形如 Item_xxx_subselect 代替普通的 Item 来表示一个子查询,整体语法树结构大致为:

例如,形如一下的 IN 子查询

select * from t1 where c1 in (select c1 from t2 where c1 > 25);

在这里插入图片描述
左侧为 Parse 结束后的语法树结构,两个 Query_block 分别对应外表 t1 和子查询 t2,除了 Query_block 和 Query_expression 可以从 t1 查询找到 t2 查询外,外表 t1 还通过 where 子句 Item_in_subselect 可以找到内表子查询 Query_block(t2),两个 Query 分别都有各自的 select list,from,where 子句。

右侧为经过 Transform 转为 semi-join 之后的语法树逻辑,这时内表子查询 t2 已经被 pullout 或 Merge 到外表查询块上,而内表条件也被 merge 到外表 where 条件中,而 t1 与 t2 也称为了的一种 semi-join 形式的嵌套查询。

Scalar 子查询的处理

对于只需返回单一值的子查询,称为 Scalar 子查询
可以是 scalar 标量比较运算符(=、!=、>、>=、<、<=)和 > ALL、< ALL、> ANY、< ANY 及其拓展形式
子查询中使用聚合函数(SUM,AVG,MAX,MIN,COUNT)返回结果等
例如:

select * from t1 where c1 > (select max(c1) from t2 where c1 > 25);

Prepare

在外表查询块 Query_block::prepare 进行 resolve 时,会 resolve where 条件,尝试解析 where 条件上的 Item 列到
实际 table field 的各种引用关系,而外表查询块的 where 条件是一个子查询 item(Item_singlerow_subselect),所以
最终会尝通过 Item_singlerow_subselect::fix_fields 来解析子查询 item 到实际 field 的引用。

Item_singlerow_subselect::fix_fields()->Item_subselect::fix_fields()->query_expr()->prepare()

子查询右侧操作数实际上是一个查询 Query_block,所以 resolve 时,会进一步调用子查询 Query_block::prepare 来
进一步 resolve/transform 子查询块,直到最终实际上是引用到 max(t2.c1) field

Optimize

子查询块的 prepare 是通过外层查询块的 resolve where 子句触发的,而 optimize 则是挪到了实际 Execute 阶段,由于
scalar 子查询最终返回的是单行单列结果,所以对实际延迟到 Execute 做子查询的 optimize 没有任何影响

Execute

scalar 子查询的执行由外层查询块在 evaluate where 条件时触发,对 Item_in_select 进行 boolean factor 的校验时,
触发子查询的 optimize 和 Execute,单行单列结果存储在子查询的 <select>

Item_singlerow_subselect::val_xxx()->Item_subselect::exec()->query_expr()->optimize()
Item_singlerow_subselect::val_xxx()->Item_subselect::exec()->query_expr()->execute()

预告:下篇继续普通 set 集合运算 subquery 的处理分析

引用

  1. Kim W. On optimizing an SQL-like nested query[J]. ACM Transactions on Database Systems (TODS), 1982, 7(3): 443-469.
  2. Ganski R A, Wong H K T. Optimization of nested SQL queries revisited[J]. ACM SIGMOD Record, 1987, 16(3): 23-33.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/342200.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++: vector

目录 1.vector的介绍 2.vector常用的接口 1.vector构造 2.迭代器iterator的使用 3.vector空间增长 4.vector的增删改查 3.vector模拟实现 如果在reverse时使用memcpy会怎么样&#xff1f; 1.vector的介绍 C中的vector是一个动态数组容器&#xff0c;可以存储任意类型的…

【算法分析与设计】二叉树的层序遍历

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 题目 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xf…

Python 自动化办公:一键批量生成 PPT

Stata and Python 数据分析 一、导读 在实际工作中&#xff0c;经常需要批量处理Office文件&#xff0c;比如需要制作一个几十页的PPT进行产品介绍时&#xff0c;一页一页地制作不仅麻烦而且格式可能不统一。那么有什么办法可以一键生成PPT呢&#xff1f;Python提供的pptx 包…

Simulink|光伏并网逆变器低电压穿越仿真模型

目录 主要内容 模型研究 1.模型总览 2.boost模块 3.Inverter模块 4.控制模块 5.信号模块 结果一览 下载链接 主要内容 该模型为光伏逆变器低电压穿越仿真模型&#xff0c;采用boost加NPC拓扑结构&#xff0c;基于MATLAB/Simulink建模仿真。模型具备中点平衡…

灭火图 - 故障发现和定位的入口

通过深入分析和解决企业在可观测性和稳定性保障方面的挑战&#xff0c;Flashcat 提出了“灭火图”这一关键概念。 灭火图以服务/模块/基础组件/基础设施等为维度&#xff0c;以聚合的视角实时度量某个特定维度的可用性&#xff08;典型指标包括时延、流量、错误、饱和度&#x…

���恒峰|配网行波型故障预警定位装置:电力系统的守护神

&#xfffd;&#xfffd;&#xfffd;在电力系统中&#xff0c;设备的正常运行对于保障供电至关重要。而配网行波型故障预警定位装置就是电力系统的守护神&#xff0c;它能够实时监测设备状态&#xff0c;提前发现故障&#xff0c;确保电力供应的稳定。本文将详细介绍配网行波…

Gradle 笔记

Gradle依赖管理&#xff08;基于Kotlin DSL&#xff09; **注意&#xff1a;**如果不是工作原因或是编写安卓项目必须要用Gradle&#xff0c;建议学习Maven即可&#xff0c;Gradle的学习成本相比Maven高很多&#xff0c;而且学了有没有用还是另一回事&#xff0c;所以&#xff…

【网络】传输层TCP协议

目录 一、概述 2.1 运输层的作用引出 2.2 传输控制协议TCP 简介 2.3 TCP最主要的特点 2.4 TCP连接 二、TCP报文段的首部格式 三、TCP的运输连接管理 3.1 TCP的连接建立(三次握手) 3.2 为什么是三次握手&#xff1f; 3.3 为何两次握手不可以呢&#xff1f; 3.4 TCP的…

【KD】2023 NeurIPS Does Graph Distillation See Like Vision Dataset Counterpart?

简介 在大规模图数据集上进行GNN训练是一个艰巨的挑战。特别是在增量学习和图结构搜索这些经常需要重复训练的场景中,训练图模型不仅消耗大量时间,还对显存和计算能力提出了严峻要求。最近,图数据集蒸馏/图压缩(Graph Dataset Distillation / Graph Condensation)方法…

Harmony 鸿蒙驱动开发

驱动开发 驱动模型介绍 HDF&#xff08;Hardware Driver Foundation&#xff09;框架以组件化的驱动模型作为核心设计思路&#xff0c;为开发者提供更精细化的驱动管理&#xff0c;让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个Host&#xff08;设备容器&#…

阿里巴巴开源联邦学习框架FederatedScope

5月5日&#xff0c;阿里巴巴达摩院发布新型联邦学习框架FederatedScope&#xff0c;声称可以在不共享训练数据的情况下开发机器学习算法&#xff0c;从而保护隐私。&#xff0c;其源代码现已在Apache 2.0许可下发布在GitHub上。 介绍 该平台被描述为一个全面的联邦学习框架&a…

compose部署tomcat

1.部署tomcat 1.1.下载相关镜像tomcat8.5.20 $ docker pull tomcat:8.5.20 1.2 在/data目录下创建tomcat/webapps目录 mkdir -p /data/tomcat/webapps 注意&#xff1a;这里是准备将宿主机的/data/tomcat/webapps映射到容器的 /usr/…

Oracle篇—分区表和分区索引的介绍和分类(第一篇,总共五篇)

☘️博主介绍☘️&#xff1a; ✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ ✌✌️擅长Oracle、MySQL、SQLserver、Linux&#xff0c;也在积极的扩展IT方向的其他知识面✌✌️ ❣️❣️❣️大佬们都喜欢静静的看文章&#xff0c;并且也会默默的点赞收藏加关注❣…

ChatGPT 引导语写法参考(翻译类引导语)

充当英语翻译和改进者 我想让你充当英文翻译员、拼写纠正员和改进员。我会用任何语言与你交谈&#xff0c;你会检测语言&#xff0c;翻译它并用我的文本的更正和改进版本用英文回答。我希望你用更优美优雅的高级英语单词和句子替换我简化的 A0 级单词和句子。保持相同的意思&am…

顶顶通呼叫中心中间件利用自动外呼进入机器人的压力测试配置流程

文章目录 前言呼入进入机器人配置流程呼入配置创建线路创建线路组创建自动外呼任务1. 实现“一端放音&#xff0c;另一端进入机器人”操作创建拨号方案—“模拟放音”呼叫路由—“internal”启用拨号方案—“模拟放音”队列外呼配置 2. 实现“两端都进入机器人”操作队列外呼配…

JavaWeb会议管理系统

相关技术&#xff1a; Servlet Tomcat jsp MySQL 有需要的可以联系我。 功能介绍&#xff1a; 会员管理系统&#xff1a;系统管理、用户管理、角色管理、菜单管理、日志管理、部门管理 会议管理&#xff1a;会议室管理、我的会员、会员纪要、修改密码、安全退出 会议室管…

C/C++读写文件和stringstream类

目录 C处理文件打开文件两种函数的区别 读文件两种函数区别其它读操作的函数fgetc&#xff1a;从文件中读取一个字符fgets&#xff1a;从文件中读取一个字符串fscanf&#xff1a;按格式从文件中读取指定内容&#xff0c;与scanf函数类似 写文件其它的常用写操作函数fputc&#…

【网站项目】基于SSM的263货物进销管理系统

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Java项目:基于ssm框架实现的电影评论系统(ssm+B/S架构+源码+数据库+毕业论文)

一、项目简介 本项目是一套ssm826基于ssm框架实现的电影评论系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#x…

Elasticsearch:2023 年 Lucene 领域发生了什么?

作者&#xff1a;来自 Elastic Adrien Grand 2023 年刚刚结束&#xff0c;又是 Apache Lucene 开发活跃的一年。 让我们花点时间回顾一下去年的亮点。 社区 2023 年&#xff0c;有&#xff1a; 5 个次要版本&#xff08;9.5、9.6、9.7、9.8 和 9.9&#xff09;&#xff0c;1 …