MySQL执行计划的作用
当我们在执行的sql语句前面加上EXPLAIN关键字,就可以模拟得到优化器执行的sql语句,从而了解MySQL是如何解析你的sql语句,然后针对执行结果进行相应的sql优化。
执行计划查询的结果主要由以下列组成,接下来就主要针对这些列进行详细解析。
id列
id列为由数字表示,是一组序号,表示执行sql语句的顺序。
id的查询结果有两种可能:
1、id相同:执行顺序由上而下
2、id不同:id值大的优先执行
select_type列
select_type表示查询的类型。
类型 | 描述 |
SIMPLE | 简单的SELECT语句(不包括UNION操作或子查询操作) |
SUBQUERY | 在SELECT或WHERE列表中包含了子查询 |
PRIMARY | 最外层的查询 |
DEPENDENT SUBQUERY | 子查询中首个SELECT,但依赖于外层的表 |
DERIVED | 用于 from 子句里有子查询的情况。 MySQL 会递归执行这些子查询, 把结果放在临时表里 |
UNION | 若第二个SELECT出现在UNION之后,则被标记为UNION |
DEPENDENT UNION | UNION操作中,查询中处于内层的SELECT(内层的SELECT语句与外层的SELECT语句有依赖关系) |
UNION RESULT | 从UNION表获取的结果的select |
UNCACHEABLE UNION | union中的第二个或者后面的不能被缓存的子查询 |
UNCACHEABLE SUBQUERY | 结果不能被缓存的子查询,外层查询需要使用的时候都要重新执行一次 |
SIMPLE
SUBQUERY、PRIMARY
DEPENDENT SUBQUERY
DERIVED
UNION、UNION RESULT
DEPENDENT UNION
table列
table列的信息主要就是用来表示属于哪张表的,上面的例子中已经很明显。
type列
type列表示的是访问类型,是比较重要的一个指标,结果值从最好到最坏依次是:
system > const > eq_ref > ref > range > index > all
一般来说,得保证查询达到range级别,最好能达到ref。
all:全表扫描
index:利用覆盖索引扫描
range:只检索给定范围的行,使用一个索引来选择行,能根据索引做范围的扫描
ref :非唯一性索引扫描,返回匹配某个单独值的所有行.
eq_ref :唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描
const :用于比较primary key或者unique索引。因为只匹配一行数据,所以很快
如将主键置于where列表中,MySQL就能将该查询转换为一个常量
system :系统表,少量数据,往往不需要进行磁盘IO
possible_keys、Key
possible_keys:表示可能使用的索引。
key:表示实际使用的索引。
上面的演示中已经有很多案例,这里也不重复介绍了。
key_len
key_len表示索引使用的字节数,根据这个值,就可以判断索引使用情况,一般来说这个值越小越好,在组合索引的时候,也可以用来判断所有的索引字段是否都被查询用到。
对于字符串类型char和varchar跟编码集也有一定关系,其中gbk占用2个字节,utf8占用3个字节。
int占4个字节,bigint占8个字节,如果允许为null就再加1。
char类型的key_len计算方式为:长度*3,如果允许为null就再加1。
varchar类型的key_len计算方式为:长度*3+2,如果允许为null就再加1。
order_number varcharl类型,长度32,编码集utf8,可以为null,所以根据公式得出:32*3+2+1=99。
修改为不允许为null,得到结果为98。字符串类型长度
数值类型
日期类型
ref列
显示索引的哪一列被使用了,如果有可能是一个常数,哪些列或常量被用于查询索引列上的值。
row列
估算出结果集行数,表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数。
Extra列
包含不适合在其他列中显示,但是十分重要的额外信息。
Using filesort
当查询中包含 order by 操作,而且无法利用索引完成的排序操作称为“文件排序”
Using temporary
表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询,group by 、order by。
Using index
表示相应的select操作用使用覆盖索引,避免访问了表的数据行。
如果同时出现using where,表明索引被用来执行索引键值的查找。
Using where 与 using join buffer
Using where
表明使用了where过滤。
using join buffer
使用了连接缓存。
impossible where
where子句的值总是false,不能用来获取任何元素。