mysql的explain(执行计划)用于解释sql的执行的过程,然后把sql的执行过程用一张表格表示出来,它并不真正的执行sql,如下图。explain能够为我们优化sql提供很好参考作用。
下面我来看下执行计划表中各个字段是什么意思
id(select的序号)
每一行数据代表一个select,id越大越先执行,id相同则从上往下执行,id为null的最后执行。
select_type(查询的类型)
SIMPLE:简单查询,没有子查询等等,简单YYDS。
PRIMART:复杂查询,包含子查询等的select,通常是最外层的查询。
SUBQUERY:子查询。
DERIVED:衍生查询,会产生临时表的查询。
UNION:联合查询,union中的第二查select开始。
table(当前行访问的表)
<derivedN>:先执行id=N的衍生查询。
<unionN,M>:表示参与联合查询的行id。
NULL:mysql能够在优化阶段分解查询语句,在执行阶段用不着再访问表或索引。例如:在索引列中选取最小值,可以单独查找索引来完成,不需要在执行时访问表。
type(如何查询行)
查询速速最快到最慢依次为:system > const > eq_ref > ref > range > index > ALL,通常情况下建议至少达到ref。
const:mysql能对查询的某部分进行优化并将其转化成一个常量。用于 primary key 或 unique key 的所有列与常数比较时,所以表最多有一个匹配行,读取1次,速度比较快。
system:const的特例,表里只有一条元组匹配时为system。
eq_ref:primary key 或 unique key 索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录。const 之外最好的联接类型,简单的 select 查询不会出现这种 type。
ref:使用普通索引或者唯一性索引的部分前缀,索引要和某个值相比较,可能会找到多个符合条件的行。
range:范围扫描通常出现在 in(), between ,> ,<, >= 等操作中。使用一个索引来检索给定范围的行。
index:扫描全索引就能拿到结果,一般是扫描某个二级索引,这种扫描不会从索引树根节点开始快速查找,而是直接 对二级索引的叶子节点遍历和扫描,速度还是比较慢。
all:扫描全表。
possible_keys
这个表示该条select可能用到的索引。
key
这个表示该条select用到的索引。
key_len
索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列,5.0.3以后版本中,char(n)和varchar(n),n均代表字符数,而不是字节数,如果是utf-8,一个数字或字母占1个字节,一个汉字占3个字节。 key_len 计算规则如下
char(n):如果存汉字长度就是 3n 字节。
varchar(n):如果存汉字则长度是 3n + 2 字节,加的2字节用来存储字符串长度,因为 varchar是变长字符串 。
tinyint:1字节
smallint:2字节
int:4字节
bigint:8字节
date:3字节
timestamp:4字节
datetime:8字节
ref
说明该select在表查找值所用到的列或常量,常见的有:const(常量),字段名(例:film.id),可以理解为where条件中等号右边的值是一个常量或一个字段。
rows
表示该select查询是要扫描到行数,不是查询结果集的行数。
extra
一些额外信息。常见的重要值如下
Using index:覆盖索引,意思是只需通过二级索引就能满足该sql的查询条件以及查询结果,不需要通过二级索引去寻找主键索引。
Using where:where条件未被索引覆盖到,就是全表扫描
Using index condition:未完全用索引,比如我们一般建立一个联合索引,有三个字段,但是现在我们的where条件里只用到了第一个或者前两个字段,这种就是Using index condition,也叫用了,但没有完全用索引。
Using temporary:使用了临时表,mysql需要创建一张临时表来处理查询。出现这种情况一般是要进行优化的。
Using filesort:文件排序,将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序。这种情况下一 般也是要考虑使用索引来优化的。可以考虑给排序字段加上索引。
Select tables optimized away:聚合函数访问字段。