查询示例
![](https://i-blog.csdnimg.cn/blog_migrate/2ba92d56f04e27f3bfdfb4e3a5da53dc.png)
id列
这一列总是包含一个编号,标识select所属的行,如果在语句中没有子查询或者联合查询,那么只会有唯一的select,于是每一行的这一列都将显示一个1。否则,内层的select语句一般会顺序编号,对应其在原始语句中的位置。
select_type列
显示了对应行是简单还是复杂select:
SIMPLE表示查询不包含子查询和union,如果查询中有任何复杂的子部分,则最外层部分标记为PRIMARY;
SUBQUERY表示包含在select列表中的子查询中的select(换句话说不在from子句中);
DERIVED表示包含在from子句的子查询中的from,MySQL会递归执行并将结果放到一个临时表中。服务器内部称其为派生表,因为该临时表是从子查询中派生来的;
UNION表示在union中的第二个和随后的select被标记为union;
UNION RESULT表示用来从UNION的匿名临时表检索结果的select。
除了这些值,SUBQUERY和UNION还可以被标记为DEPENDENT和UNCACHEABLE。DEPENDENT意味着select依赖于外层查询中发现的数据。UNCACHEABLE意味只select中的某些特性阻止结果被缓存于Item_cache中。
table列
显示对应行正在访问哪个表,通常是表名或者该表的别名(如果SQL定义了别名)。
type列
访问类型,下面依次从最差到最优:
ALL表示全表扫描,MySQL必须扫描整个表,从头到尾,来找到所需要的行(有个例外如使用了limit或者extra列中显示了Using distinct/not exists);
index跟全表扫描一样,只是扫描时按索引次序进行而不是行。主要优点是避免了排序,最大缺点是要承担按索引次序读取整个表的开销。如果在extra列中看到Using index,说明MySQL正在使用覆盖索引,只扫描索引的数据,而不是按索引次序的每一行,它比按索引次序全表扫描的开销要少很多;
range范围扫描,是一个有限制的索引扫描,开始于索引的某一点,返回匹配这个值域的行。比全索引扫描好一些,因为用不着遍历全部索引。显而易见的范围扫描是带有between或在where子句里带有>的查询;
ref是一种索引访问,返回所有匹配某个单个值的行。然而,它可能会找到多个符合条件的行,此类索引访问只有当使用非唯一性索引或者唯一性索引的非唯一性前缀时才会发生。ref_or_null是ref的一个变体,它意味着MySQL必须在初次查找的结果里进行第二次查找以找出NULL条目;
eq_ref这种索引查找,MySQL知道最多只返回一条符合条件的记录。这种访问方法可以在MySQL使用主键或者唯一性索引查找时看到;
const,system当MySQL能对查询的某部分进行优化并将其转换成一个常量时,它就会使用这些访问类型;
NULL这种访问方式意味着MySQL能在优化阶段分解查询语句,在执行阶段甚至不用在访问表或者索引。
possible_keys列
这一列显示了查询可以使用哪些索引,这是基于查询访问的列和使用的比较操作符来判断的。这个列是在优化过程的早期创建的,因此有些罗列出来的的索引可能对于后续优化过程是没用的。
key列
显示MySQL决定采用哪个索引来优化对该表的访问。如果该索引没有出现在possible_keys列中,那么MySQL选用它是出于另外的原因如可能选择了一个覆盖索引,哪怕没有where子句。换言之,possible_keys揭示了哪一个索引有助于高效行查找,而key显示的是优化采用的哪一个索引可以最小化查询成本。
key_len列
显示了MySQL在索引里使用的字节数,可通过该列计算查询中使用的索引的长度。
ref列
显示了之前的表在key列记录的索引中查找值所用的列或常量
rows列
表示MySQL预估的为了找到所需的行而要读取的行数。根据表的统计信息和索引的选用情况,这个估算可能很不精确。通过把所有rows列值相乘,可以粗略的估算出整个查询会检查的行数。
要记住这个数字是MySQL认为它要检查的行数,而不是结果集里的行数。
filtered列
这一列是MySQL5.1里新加的,它显示的是针对表里符合某个条件(where子句或联结条件)的记录数所做的一个悲观估算的百分比。
Extra列
这一列包含的是不适合在其他列显示的额外信息。常见的最重要的值有:
Using index表示MySQL将使用覆盖索引,以避免回表查询。不要把覆盖索引和index访问类型混淆了;
Using where表示MySQL服务器将在存储引擎检索行后再进行过滤;
Using temporary表示MySQL在对查询结果排序时会使用一个临时表;
Using filesort表示MySQL会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。MySQL有两种文件排序算法,两种都可以在内存或磁盘上完成。但explain不会告诉你MySQL使用的是哪种,也不会告诉你排序是在内存还是磁盘上完成;
Range checked for each record(index map:N)表示没有好用的索引,新的索引将在联接的每一行上重新估算。N是显示在possible_keys列中索引的位图,并且是冗余的;
Using union表示MySQL运用了索引合并策略,索引合并策略有时是一种优化的结果,但实际上更多时候说明了表上的索引建的很糟糕。
主要关注以下几个字段信息.
id: select子句或表执行顺序, id相同, 从上到下执行, id不同, id值越大, 执行优先级越高.
type: type主要取值及其表示sql的好坏程度(由好到差排序):system > const > eq_ref > ref > range > index > ALL. 保证range, 最好到ref.
key: 实际被使用的索引列.
ref: 关联的字段, 常量等值查询, 显示为const, 如果为连接查询, 显示关联的字段.
Extra: 额外信息, 使用优先级using index > using filesort > using temporary.