Mysql执行计划Explain详解

通过explain工具可以获取到要执行sql的执行计划结果,执行计划可以充分利用索引和优化sql语句,那么来解析一下explain执行结果各个字段的含义。
在这里插入图片描述

1. id:id列的编号是 select 的序列号,一条完整的sql中有几个 select 就会有几个id,id可以存在相同的,id的顺序是按 select
出现的顺序增长的。id列越大执行优先级越高,id相同则从上往下执行,id为NULL最后执行。

下图中执行的sql可以看到id的变化。Id=2的对应select * from student where name = "student1"语句,会先执行。
图 1-1
下图中执行的sql可以看到id是相同的,可以认为是一组执行的sql。
在这里插入图片描述

2. select_type:查询的类型,主要用来区分查询类型。其中包含普通查询,子查询,联合查询等复杂查询。

SIMPLE:简单查询。查询不包含子查询和union。
在这里插入图片描述
PRIMARY:复杂查询中最外层的 select。
在这里插入图片描述
SUBQUERY:在select或者where中的子查询,不包含在form的表中。
在这里插入图片描述
DERIVED:包含在 from 子句中的子查询。MySQL会将结果存放在一个临时表中,也称为衍生表。衍生表的查看需要通过sql语句set session optimizer_switch=‘derived_merge=off’;来开启,否则在explain的查询结构中是不显示的。
在这里插入图片描述
UNION:在第二个select之前出现UNION,UNION也会出现一个衍生表,衍生表执行顺序是最后一个。
在这里插入图片描述

3. table:这一列表示 explain 的一行正在访问哪个表。当 from 子句中有子查询时,table列是 >格式,表示当前查询依赖 id= 的查询,于是先执行 id=N 的查询。当有 union 时,UNION RESULT > 的 table 列的值为,1和2表示参与 union 的 select 行id。**如下图

在这里插入图片描述在这里插入图片描述

4. partitions:代表分区中的命中情况,非分区表,该选项为NULL。

5. type:关联类型或者访问类型,该字段比较重要,是sql查询的一个指标类型。最优到最差的顺序依次为:system > const > eq_ref > ref > range > index > ALL。一般来说,得保证查询达到range级别,最好达到ref。

System,const :sql在查询过程中条件是通过索引(primary key 或 unique key)匹配的,查询结果最多只有一行,查询结果比较快。system是const的特例,表里只有一条元组匹配时为system,可以理解为表中只有一条数据。
Mysql执行计划Explain详解_第1张图片
eq_ref:primary key 或 unique key 索引的所有部分被连接使用 ,表中只会有一条记录关联。
Mysql执行计划Explain详解_第2张图片
ref:sql使用非唯一索引,查询结果可以存在多行。
Mysql执行计划Explain详解_第3张图片
range:范围扫描通常出现在 in(), between ,> ,<, >= 等操作中。使用一个索引(非索引字段可能会扫描全表)来检索给定范围的行。
在这里插入图片描述
Index:扫描全索引就能拿到结果,一般是扫描某个二级索引,这种扫描不会从索引树根节点开始快速查找,而是直接
对二级索引的叶子节点遍历和扫描,速度还是比较慢的,这种查询一般为使用覆盖索引,二级索引一般比较小,所以这种通常比ALL快一些。
如下图,表中存在了两个索引,在mysql中默认为二级索引小于以及索引,他会优先扫描二级索引,所以图中使用的是name的索引内。
Mysql执行计划Explain详解_第4张图片
all:全表扫描。

6. possible_keys:显示可能应用在这张表的索引。查询涉及到的字段上若存在索引,则该索引被列出,但不一定用到。可能出现 possible_keys 列有值,而 key列 显示 NULL 的情况,这种情况是因为表中数据不多,mysql认为索引对此查询帮助不大,选择了全表查询。

7. key:这一列显示mysql实际采用哪个索引来优化对该表的访问。

如果没有使用索引,则该列是 NULL。如果想强制mysql使用或忽视possible_keys列中的索引,在查询中使用 force index、ignore index。

用法:select * from teacher force index(update_time) where **=**;

8. key_len:这一列显示了mysql在索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列。

key_len计算规则如下:
		字符串:char(n)varchar(n)5.0.3以后版本中,n均代表字符数,而不是字节数,如果是utf-8,一个数字或字母占1个字节,一个汉字占3个字节
			char(n):如果存汉字长度就是 3n 字节;
			varchar(n):如果存汉字则长度是 3n + 2 字节,加的2字节用来存储字符串长度,因为varchar是变长字符串;
		数值类型:
			tinyint:1字节
			smallint:2字节
			int4字节
			bigint:8字节  
		时间类型: 
			date:3字节
			timestamp:4字节
			datetime:8字节

如果字段允许为 NULL,需要1字节记录是否为 NULL;索引最大长度是768字节,当字符串过长时,mysql会做一个类似左前缀索引的处理,将前半部分的字符提取出来做索引。
Mysql执行计划Explain详解_第5张图片

9. ref:这一列显示了在key列记录的索引中,表查找值所用到的列或常量,常见的有:const(常量,可以理解为where条件的常量,有几个字段对应几个常量),字段名(例:test.student_teacher.student_id)。如下图

Mysql执行计划Explain详解_第6张图片

10.rows:这一列是mysql认为它在执行过程中要读取并检测的预估值行数,注意这个不是结果集里的行数。

11.filtered:该列最后实际查询行数和mysql预估要读取行数的一个百分比,越大越好。

如下图,预计会得到100条记录,也就是rows列展示的记录数。接下来MySql会使用额外的查询条件对这100行记录做二次过滤,最终得到符合查询语句的10条记录,也就是100条记录的10%。而10%就是filtered的值。更完美的情况下,应该是使用某个索引,直接搜索出10条记录并且过滤掉另外90%的记录。

因此一个比较低filtered值表示需要有一个更好的索引,假如type=all,表示以全表扫描的方式得到1000条记录,且filtered=0.1%,表示只有1条记录是符合搜索条件的。此时如果加一个索引可以直接搜出来1条数据,那么filtered就可以提升到100%。

由此可见,filtered=100%确实是要比10%要好。
在这里插入图片描述

12.Extra:

Using index:使用覆盖索引

覆盖索引定义:mysql执行计划explain结果里的key有使用索引,如果select后面查询的字段都可以从这个索引的树中获取,这种情况一般可以说是用到了覆盖索引,extra里一般都有using index;覆盖索引一般针对的是辅助索引,整个查询结果只通过辅助索引就能拿到结果,不需要通过辅助索引树找到主键,再通过主键去主键索引树里获取其它字段值(这里涉及到一个回表的概念:回表就是说sql在执行的过程中,sql查询结果需要查询表中所有的字段,但是查询字段使用到的索引是辅助索引,在mysql索引中,辅助索引是不存储所有字段的完整信息的,想要获取完整的字段只能先查出辅助索引关联的主键索引,再通过辅助索引关联的主键到主键索引中查找叶子节点的所有信息)。如下图:
Mysql执行计划Explain详解_第7张图片

Using where:使用 where 语句来处理结果,并且查询的列未被索引覆盖

下图中,表teacher中不存在name字段额索引,where条件通过name字段来全表搜索的。
Mysql执行计划Explain详解_第8张图片

Using filesort:将用外部排序而不是索引排序(获取到查询结果,在内存中建立一块临时的缓存池进行排序),数据较小时从内存排序,否则需要在磁盘完成排序。这种情况下一般也是要考虑使用索引来优化的。

下图中,红框中表student字段name有索引,mysql会直接在缓存辅助索引中查询数据(mysql的索引页数据是有序的);蓝框中表teacher字段name不存在索引,会通过缓存池来进行排序;
Mysql执行计划Explain详解_第9张图片

Using index condition:查询的列不完全被索引覆盖,,where条件字段是一个范围查找;也包含索引不完全覆盖。

下图中,红框1索引字段是一个范围查找;红框2不满足索引最左原则,and字段未生效。
Mysql执行计划Explain详解_第10张图片

Select tables optimized away:使用某些聚合函数(比如 max、min)来访问存在索引的某个字段。Mysql索引种,数据都是有序的,max,min不需要走索引,直接在缓存池种获取即可。

在这里插入图片描述

Using temporary:mysql需要创建一张临时表来排序查询,一般用于group by 或者order by 等当中。

单路排序:一次性取出满足条件行的所有字段,然后在sort buffer缓存中进行排序;

双路排序:首先根据相应的条件取出相应的排序字段和可以直接定位行数据的行 ID,然后在 sort buffer 中进行排序,排序完后需要再次取回其它需要的字段;

Mysql 通过比较系统变量 max_length_for_sort_data(默认1024字节) 的大小和需要查询的字段总大小来判断使用哪种排序模式。

Mysql官网网站Explain文档:https://dev.mysql.com/doc/refman/5.6/en/explain-output.html

你可能感兴趣的:(Mysql,mysql,数据库,sql)