MySQL子查询优化---目标列中的子查询执行情况分析-02

接续上一篇:

MySQL子查询优化---目标列中的子查询执行情况分析

http://blog.163.com/li_hx/blog/static/18399141320154291133386/

 

7
mysql> select (select max(a) from t as t2) from t as t1;
+------------------------------+
| (select max(a) from t as t2) |
+------------------------------+
|                            2 |
|                            2 |
+------------------------------+

问题就这样又来了:究竟这个示例中的子查询,会被执行几次?
回到上一篇的标题5,我们给出了一个循环算法,用蓝色字体说明了“子查询返回的结果有多行”的情况,在这种情况下MySQL将报告错误。
而第7条中给出的是相对于第5条中的示例改造后的例子,差别在于第7条满足了“目标列中的子查询需是标量子查询的要求”。
因为第7条中的示例不满足退出条件,所以,我们可以推知,子查询一定会执行2次,这是因为t1中有2条元组。

但是,真正的答案是:此示例中的子查询只被执行了一次。
为什么?
仔细观察子查询,select max(a) from t as t2,除了和父查询都基于同一个表t外,2者之间没有其他关系。
数据库中有相关子查询和非相关子查询的概念,《数据库查询优化器的艺术》一书P19给出它们的含义,如下图:

MySQL子查询优化---目标列中的子查询执行情况分析-02 - 那海蓝蓝 - 那海蓝蓝的博客

 

相关子查询,有另外名字,叫做“重复子查询”,意思是在执行过程中,子查询依靠外部查询获得值。这意味着子查询是重复执行的,为外部查询可能选择的每一行均执行一次。
而非相关子查询,就可叫做“非重复子查询”,意思是执行一次即可。
所以,本示例“子查询只被执行了一次”就不难理解,因为本示例给出的是一个“目标列中出现的是非相关子查询”。
MySQL的执行器,把这个“非相关子查询”的结果缓存了起来,所以这个子查询就不需要因父表的元组数而被多次执行了。

8 相关子查询的例子
注意where子句,“t2.a=t1.b”使得t1和t2建立了关系。这就是相关子查询。
mysql> select (select max(a) from t as t2 where t2.a=t1.b) as MAX, t1.* from t as t1;
+------+------+------+
| MAX  | a    | b    |
+------+------+------+
|    1 |    1 |    1 |   <--b值为1,使得子查询执行一次,得出结果为1
|    2 |    2 |    2 |   <--b值为2,使得子查询执行一次,得出结果为2
+------+------+------+
2 rows in set (0.01 sec)
子查询的结果受到父表的变量的影响,其结果不同,不存在被缓存的可能。

mysql> explain select (select max(a) from t as t2 where t2.a=t1.b) as MAX, t1.* from t as t1;
+----+--------------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type        | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+--------------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | PRIMARY            | t1    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    2 |   100.00 | NULL        |
|  2 | DEPENDENT SUBQUERY | t2    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    2 |    50.00 | Using where |
+----+--------------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
2 rows in set, 2 warnings (0.01 sec)

"说明: DEPENDENT SUBQUERY",表示依赖关系,存在关联关系的 相关子查询,会被嵌套执行.


9 推广
思考问题:如果子查询不是在目标列,而是在FROM子句中,情况又会怎么样?
答案与此(此,指代"目标列中的子查询执行情况")相同,原因请思考.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值