【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 中,

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.

你可能感兴趣的:(MySQL,8.1,源码,mysql,数据库)