一、EXPLAIN信息

二、数据准备-表 single_table
三、EXPLAIN字段说明
3.1、id
查询语句中每出现一个
SELECT
关键字,设计MySQL的大佬就会为它分配一个唯一的id
值
3.1.1、多表连接
对于
连接查询
来说,一个SELECT
关键字后边的FROM
子句中可以跟随多个表
,所以在连接查询的执行计划中,每个表都会对应一条记录,但是这些记录的id值都是相同的
- SQL
EXPLAIN
SELECT *
FROM single_table s1
INNER JOIN single_table2 s2;
-
EXPLAIN结果
EXPLAIN-多表连接-但是id相同.png
-
小结
在连接查询的执行计划中,每个表都会对应一条记录,这些记录的id列的值是相同的,出现在前面的表表示驱动表,出现在后边的表表示被驱动表
。所以从上面的EXPLAIN输出中我们可以看出,查询优化器
准备让s1表作为驱动表
,让s2表作为被驱动
表来执行查询
3.1.2、子查询可以有 多个id值
- SQL
DESC
SELECT *
FROM single_table s1
WHERE s1.key1 IN (SELECT s2.key2 FROM single_table2 s2)
OR s1.key3 = 'a';
-
EXPLAIN
image.png
3.1.3、包含UNION子句的查询
-
UNION
结果去重
DESC
SELECT *
FROM single_table
UNION
SELECT *
FROM single_table2;
-
EXPLAIN
image.png
-
小结
正如上面的查询计划中所示,
UNION
子句是为了把id
为1
的查询和id
为2
的查询的结果集合并起来并去重
,所以在内部创建了一个名为<union1, 2>
的临时表(就是执行计划第三条记录的table列的名称),id为NULL表明这个临时表是为了合并两个查询的结果集而创建的
-
UNION ALL
结果不去重
DESC
SELECT *
FROM single_table
UNION ALL
SELECT *
FROM single_table2;

3.2、select_type
设计MySQL的大佬为每一个
SELECT
关键字代表的小查询
都定义了一个称之为select_type
的属性,意思是我们只要知道了某个小查询的select_type属性
,就知道了这个小查询
在整个大查询
中扮演了一个什么角色

3.2.1、SIMPLE
查询语句中
不包含UNION
或者子查询
的查询都算作是SIMPLE
类型
3.2.2、PRIMARY
对于包含
UNION
、UNION ALL
或者子查询
的大查询来说,它是由几个小查询组成的,其中最左边
的那个查询的select_type
值就是PRIMARY
- SQL
DESC
SELECT *
FROM single_table
UNION
SELECT *
FROM single_table2;
DESC
SELECT *
FROM single_table
UNION ALL
SELECT *
FROM single_table2;
3.2.3、UNION
对于包含
UNION
或者UNION ALL
的大查询来说,它是由几个小查询
组成的,其中除了最左边的那个小查询
以外,其余的小查询的select_type
值就是UNION
3.2.4、UNION
MySQL选择使用
临时表
来完成UNION
查询的去重工作
,针对该临时表
的查询的select_type
就是UNION RESULT
3.2.5、SUBQUERY
包含
子查询
的查询语句不能够转为对应的semi-join
的形式,并且该子查询
是不相关子查询
,并且查询优化器决定采用将该子查询物化
的方案来执行该子查询时,该子查询的第一个SELECT关键字代表的那个查询的select_type
就是SUBQUERY
- SQL
DESC
SELECT *
FROM single_table s1
WHERE s1.key1 IN (SELECT key2 FROM single_table2 s2)
OR s1.key3 > 'a';
- 小结
外层查询的
select_type
就是PRIMARY
,子查询的select_type
就是SUBQUERY
。需要大家注意的是,由于select_type为SUBQUERY的子查询由于会被物化,所以只需要执行一遍
3.2.6、DEPENDENT SUBQUERY
包含子查询的查询语句不能够转为对应的
semi-join
的形式,并且该子查询是相关子查询
,则该子查询的第一个SELECT
关键字代表的那个查询的select_type
就是DEPENDENT SUBQUERY
- SQL
EXPLAIN
SELECT *
FROM single_table s1
WHERE key1 IN (SELECT key1 FROM single_table2 s2 WHERE s1.key2 = s2.key2)
OR key3 = 'a';
- 小结
select_type为DEPENDENT SUBQUERY的查询可能会被执行多次
3.2.7、DEPENDENT UNION
在包含
UNION
或者UNION ALL
的大查询中,如果各个小查询
都依赖于外层查询
的话,那除了最左边的那个小查询之外,其余的小查询的select_type
的值就是DEPENDENT UNION
- SQL
EXPLAIN
SELECT *
FROM single_table s1
WHERE key1 IN
(SELECT key1 FROM single_table2 s2 WHERE key1 = 'a' UNION SELECT key1 FROM single_table s3 WHERE key1 = 'b');
- 小结
这个查询比较复杂啊,
大查询
里包含了一个子查询
,子查询
里又是由UNION
连起来的两个小查询
。从执行计划中可以看出来,SELECT key1 FROM single_table2 s2 WHERE key1 = 'a'
这个小查询
由于是子查询
中第一个查询,所以它的select_type
是DEPENDENT SUBQUERY
,而SELECT key1 FROM single_table s3 WHERE key1 = 'b'
这个查询的select_type
就是DEPENDENT UNION
3.2.8、DERIVED
对于采用
物化
的方式执行的包含派生表
的查询,该派生表对应的子查询的select_type
就是DERIVED
- SQL
EXPLAIN
SELECT *
FROM (SELECT key1, COUNT(*) AS c FROM single_table s1 GROUP BY key1) AS derived_s1
WHERE c > 1;
3.2.9、MATERIALIZED
当查询优化器在执行包含
子查询
的语句时,选择将子查询物化
之后与外层查询
进行连接查询
时,该子查询对应的select_type
属性就是MATERIALIZED
- SQL
EXPLAIN
SELECT *
FROM single_table s1
WHERE key1 IN (SELECT key1 FROM single_table s2);

- 小结
执行计划的第三条记录的
id
值为2
,说明该条记录对应的是一个单表查询
,从它的select_type
值为MATERIALIZED
可以看出,查询优化器是要把子查询
先转换成物化表
。然后看执行计划的前两条记录的id
值都为1
,说明这两条记录对应的表进行连接查询
,需要注意的是第二条记录的table
列的值是<subquery2>
,说明该表其实就是id
为2
对应的子查询
执行之后产生的物化表
,然后将s1
和该物化表
进行连接查询
网友评论