您的位置:首页 > 数据库 > MySQL

MySQL执行计划辨析--子查询的相关显示项的含义

2017-03-13 19:07 603 查看
有朋友问,在MySQL的执行计划中,“DEPENDENT SUBQUERY” 和 “SUBQUERY”到底是什么含义?
官方文档解释如下:
SUBQUERY
First
SELECT
in subquery
DEPENDENT SUBQUERY
First
SELECT
in subquery, dependent on
outer query
这个解释是什么含义呢?
先看如下示例:
1 创建表并插入数据如下:
CREATE TABLE t1 (a INT, b INT);
CREATE TABLE t2 (c INT, d INT);
CREATE TABLE t3 (e INT);
INSERT INTO t1 VALUES (1,10), (2,10);
INSERT INTO t2 VALUES (2,10), (2,20);
INSERT INTO t3 VALUES (10), (30);

2 获取如下查询的执行计划:

3 观察执行计划,发现如下:

3.1 t31表是一个子查询,select_type的值为 SUBQUERY
3.2 t32表是一个子查询,select_type的值为 DEPENDENT SUBQUERY
3.3 t2表上的子查询被上拉优化,和t1表变为内连接
3.4 执行计划中的id列的值,告诉我们,作为子查询(优化后的即不可优化的子查询),其初始次序首次为3,其次为4
3.5 根据3.4,可以知道第一个子查询是t31表对应的查询,所以执行计划显示“SUBQUERY”,即:First
SELECT
in subquery,意思是“子查询中的第一个SELECT语句”
3.6 根据3.5的思路,可以推知DEPENDENT SUBQUERY的意思是“子查询中的第一个SELECT语句但子查询依赖于外表”

4 为什有“DEPENDENT”依赖的含义呢?
继续执行命令如下:
mysql> SHOW WARNINGS;
...
/* select#1 */ select `d`.`t1`.`a` AS `a`,`d`.`t1`.`b` AS `b` from `d`.`t1` semi join (`d`.`t2`)
where
(
    (`d`.`t2`.`c` = `d`.`t1`.`a`)
    and <nop>
        (<in_optimizer>
            (
                (/*select#3 */ select `d`.`t31`.`e` from `d`.`t3` `t31`),
                <exists>(
                    /* select#4 */ select 1 from `d`.`t3` `t32`
                    where (`d`.`t1`.`b`
                        and <if>(outer_field_is_not_null,
                        (
                            (<cache>((/* select#3 */ select `d`.`t31`.`e` from `d`.`t3` `t31`)) < `d`.`t32`.`e`)
                            or isnull(`d`.`t32`.`e`)
                        ), true))
                    having <if>(outer_field_is_not_null, <is_not_null_test>(`d`.`t32`.`e`), true)
                )
            )
        )
)
...
发现t32这个表上是有依赖外表t1的条件的,这个条件在t32这个表上的WHERE条件中,为“WHERE t1.b”,这使得t32不得不依赖于t1.
所以SHOW WARNINGS显示的结果告诉我们,服务器是要判断“d`.`t1`.`b`”的值的。所以依赖就是与外表有关联,属于“相关子查询”(不相关子查询,被物化优化)。

5 那么,官方文档的解释,“First
SELECT
in subquery”中的first是什么意思呢?
修改一下查询语句,得到执行计划如下:
mysql> EXPLAIN SELECT * FROM t1 WHERE t1.a IN (SELECT c FROM t2 WHERE (SELECT e FROM t3 as t31) < SOME (SELECT e FROM t3 as t32 WHERE t1.b) AND (SELECT e FROM t3 as t33) < SOME (SE
LECT e FROM t3 as t34 WHERE t1.b));
+----+--------------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------------------------------------------------------------
-+
| 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 | Using where
|
| 1 | PRIMARY | t2 | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 50.00 | Using where; FirstMatch(t1); Using join buffer (Block Nested Loop)
|
| 6 | DEPENDENT SUBQUERY | t34 | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 100.00 | Using where
|
| 5 | SUBQUERY | t33 | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 100.00 | NULL
|
| 4 | DEPENDENT SUBQUERY | t32 | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 100.00 | Using where
|
| 3 | SUBQUERY | t31 | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 100.00 | NULL
|
+----+--------------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------------------------------------------------------------
-+
6 rows in set, 3 warnings (0.00 sec)

观察新增的条件蓝色字体部分,与原始SQL中的条件红色字体部分,几乎一样,只是表的别名不同。我们让一样的子查询出现2次,就是想验证官方文档中的“First”的含义,根据执行计划可以看出,有2个SUBQUERY,同时也有2个DEPENDENT SUBQUERY,所以不必纠结于“First”的字面含义了(可以认为官方文档描述有错误)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: