一、什么是explain
使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句。分析你的查询语句或是表结构的性能瓶颈。
二、explain用法
2.1 id列
2.11 id相同,执行顺序由上往下
2.12 如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行。
2.13 id相同不同,同时存在
解释:id值如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行``。
2.2 select_type列
select_type表示对应行是简单还是复杂的查询
- simple:简单查询,查询不包含子查询和union
- primary:复杂查询中的最外层的select
- subqueery:包含在select中的子查询(不在from子句中)
- devived:临时表查询,包含在from子句中的子查询,mysql会将结果存放在一个临时表中(也称派生表)
union:在union中的第二个和随后的select

2.3 table列
这一列表示explain正在访问哪个表,当from子句中有子查询时,table列是
当有union时,union result的table列的值为
2.4 type列(重点)
这一列表示关联类型或访问类型,即MySQL决定如何查找表中的行,查找数据行记录的大概范围。依次从最优到最差分别为:system > const > eq_ref > ref > range > index > ALL**。一般来说需要保证查询达到_r__ange级别,最好达到ref。_
2.4.1 ALL:全表扫描。扫描你的聚簇索引的所有叶子节点。通常情况下这需要增加索引来进行优化了
2.4.2 index:扫描全索引就能拿到结果,一般是扫描某个二级索引,这种扫描不会从索引树根节点开始快速查找,而是直接 对二级索引的叶子节点遍历和扫描,速度还是比较慢的,这种查询一般为使用覆盖索引,二级索引一般比较小,所以这 种通常比ALL快一些。(name为索引,id和name都在二级索引树中)
2.4.3 range:只索引给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引,一般就是在你的where语句中出现了between、< 、>、in等查询,这种范围扫描索引扫描比权标扫描要好,因为它只需要开始与索引的某一点,而结束于另一点,不用扫描全部索引。
2.4.4 ref :相比 eq_ref,不使用唯一索引,而是使用普通索引或者唯一性索引的部分前缀,索引要和某个值相比较,可能会 找到多个符合条件的行。
1)、简单的select查询,非唯一索引(name为非唯一索引)
2)、关联表查询,col_role_id是col_role_id和col_id的联合索引,这里使用到了cx_admin_role的左边前缀 col_id部分。
2.4.5 eq_ref :primary key 或 unique key 索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录。这可能是在 const 之外最好的联接类型了,简单的 select 查询不会出现这种 type,主键索引和唯一索引的关联查询为eq_ref;
2.4.6 system、const:mysql能对查询的某部分进行优化并将其转化成一个常量(可以看show warnings 的结果)。用于 primary key 或 unique key 的所有列与常数比较时,所以表最多有一个匹配行,读取1次,速度比较快;system是 const的特例,表里只有一条元组匹配时为system,表里只有一条数据。 
2.4.7 null**:mysql能够在优化阶段分解查询语句,在执行阶段用不着再访问表或索引。例如:在索引列中选取最小值,可 以单独查找索引来完成,不需要在执行时访问表
2.5 possible_keys列
possible_keys显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。possible_keys显示为空,表示没有用到索引。
2.6 key列
这一列显示mysql实际采用哪个索引来优化对该表的访问。 如果没有使用索引,则该列是 NULL。如果想强制mysql使用或忽视possible_keys列中的索引,在查询中使用 force index、ignore index。
2.7 key_len列
这一列显示了mysql在索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列。 举例来说,cx_admin的联合索引 col_role_id 由 col_admin_id 和 col_role_id两个int列组成,并且每个int是4字节。通 过结果中的key_len=4可推断出查询使用了第一个列:col_admin_id列来执行索引查找
key_len计算规则
- 字符串,char(n)和varchar(n),5.0.3以后版本中,n均代表字符数,而不是字节数,如果是utf-8,一个数字 或字母占1个字节,一个汉字占3个字节
char(n):如果存汉字长度就是 3n 字节
varchar(n):如果存汉字长度就是 3n+2 字节,加2个字节用来存储字符串长度
- 数值类型
- tinyint - 1字节
- smallint - 2字节
- int - 4字节
- bigint - 8字节
- 时间类型
- date - 3字节
- timestamp - 4字节
- datetime - 8字节
注意:如果字段允许为 NULL,需要 1 字节记录是否为 NULL
_索引最大长度是768字节,当字符串过长时,mysql会做一个类似左前缀索引的处理,将前半部分的字符提取出来做索 引。
2.8、ref列
这一列显示了在key列记录的索引中,表查找值所用到的列或常量,常见的有:const(常量),字段名(例:film.id)
2.9、rows列
这一列是mysql估计要读取并检测的行数,注意这个不是结果集里的行数。
2.10、extra列
这列显示的是扩展信息,常见的重要值如下
- Using index:使用覆盖索引
覆盖索引定义:整个查询结果只通过辅助索引就能拿到结果,不需要通过辅助索引树找到主键,再通过主键去主键索引树里获取其它字段值
- Using where:使用 where 语句来处理结果,并且查询的列未被索引覆盖,需要优化

**
- Using temporary:mysql需要创建一张临时表来处理查询。出现这种情况一般是要进行优化的,首先是想到用索 引来优化

