Mysql中Explain详解
当我们使用索引的时候,通常会用explain来检查我们索引使用的情况。
id列:
这一列总是包含一个编号,标示select所属的行。如果在语句当中没有子查询或联合,那么只会有的select,于是每一个在这个列中都将显示一个1.否则,内层的select语句一般会顺序编号,对应与其在原始语句中的位置。
Mysql将select查询分为简单和复杂类型,复杂类型可分成三大类:简单子查询,所谓的派生表(在from字句中的子查询),以及union查询。
1、这个是简单的子查询:
2、from子句中的子查询和联合给id列增加了更多的复杂性。下面是一个from字句中的基本子查询。
这个查询语句执行时有一个匿名临时表。MySQL内部通过别名(der)在外层查询中引用这个临时表,在更复杂的查询中可以看到ref列。
3、下面是一个UNION查询。
Explain select 1 union all select 1;
注意union结果输出中的额外行。union结果总是放在一个匿名临时表中,之后MySQL将结果读取到临时表临时表外。临时表并不在原sql中出现,因此他的id列是null,与之前的例子相比(演示子查询的那个from字句中),从这个查询产生的临时表在结果中出现在最后一行,而不是第一行。
select_type列
这一列显示对应行是简单还是复杂的select(如果是后者,那么是三种复杂类型的哪一种),simple值意味着查询中不包括子查询和union。如果查询有任何复杂的子部分,则最外层部分标记为primary,其他部分标记如下。
subquery:包含在select列表中的子查询中的select(就是不再from字句中)标记为subquery。
derived:derived值用来表示包含在from字句中的子查询中的select,MySQL会递归执行并将结果放到一个临时表中。服务器内部称其为“派生表”,因为该临时表是从子查询中派生出来的。
union:在union中的第二个和随后的select被标记为union。第一个select被标记就好像它以部分外查询来执行。这就是之前的例子中的union中的第一个select显示为primary的原因。如果union被from字句中的子查询包含,那么它的第一个select会标记为derived;
union result
用来从union的匿名临时表检索结果的select被标记为union result。
Type列
访问SQl的类型,也就是MySQL决定查找表中的行。下面是最重要的访问方法,一次从差到最优。
ALL:这就是人们所称的全表扫描,通常意味着MySQL必须扫描整张表,从头到尾,去找到需要的行。(这里也有一个以为,例如在查询中里使用limit,或者在extra列中显示“using distinct/not exists”。)
Index:这个跟全表扫描一样,只是MySQL扫描表时按照索引的次序进行而不是行。他的主要优点是避免了排序;最大的缺点是要承担按索引次序读取整个表的开销。这通常意味着若按随机次序访问行,开销将会非常大。
Range:范围扫描就是一个有限制的索引扫描,它开始于索引的某一点,返回匹配这个值域的行。这比全索引扫描好一些,因为它用不到遍历全部索引。显而易见的范围扫描时带有between或在where字句带有>的查询。
当MySQL使用索引区查找一系列值的时候,例如in()和or()列表,也会显示范围扫描。然而两者相当于不同的访问类型,在性能上有重要的差距。在我博客有相关记载。
Ref:这是一种索引访问(有时候也叫索引查找),他返回所有匹配某个单个值的行。然而,他可能会找到多个符合条件的查询,因此,它是查找和扫描的混合体。此类索引访问只有当使用非唯一索引或者唯一性索引的非唯一性前缀时才能发生。把它叫做ref是因为索引要跟某个参考值相比较。这个参数值或者是一个常数,或者是来自多表查询前一个表里的结果值。
Eq_ref:使用这种索引查找,MySQL知道最多只返回一条符合条件的记录。这种访问方法可以再MySQL使用主键或者唯一性索引查找时看到,它会将他们与某个参考值作比较。MySQL对于这类访问类型的优化做的非常好,因为他知道无须估计匹配行的范围或在找到匹配行后再继续查找。
Const,system:当MySQL能对查询的某部分进行优化并将其转换成一个常量时,他就会使用这些访问类型。举例来说,如果你通过将某一行的主键放入where子句里的方式来选取此行的主键,MySQL就能把这个查询转换成一个常量。然后就可以高效地将表从联接执行中移除。
Null:这种访问方式意味着MySQL能在优化阶段分解查询语句,在执行阶段甚至用不着在访问表或者索引。例如,从一个索引列里选取最小值可以通过单独查找索引来完成,不需要在执行时访问表。
Key列:
这一列显示了查询可以使用哪些索引。
Ref列:这一列显示之前的表在key列记录的数据索引中查找值索引的列或者常量。
Rows列:估计这个查找到所需要的行而读取的行数。是个约数。
Extra列:
这一列包含的是不适合在其他列显示的额外信息。
“Using index”:此值表示MySQL将使用覆盖索引,以避免访问表。不要把覆盖索引和index类型弄混。
“Using where”:此值以为这MySQL服务器将在存储引擎检索行后再进行过滤。许多where条件里涉及到索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带有where子句查询都会显示“using where”。有时,“using where” 的出现就是一个暗示,查询可收益与不同的索引。
Using temporary:这意味着MySQL在对查询结果排序时会使用一个临时表。
Using filesort:这意味着MySQL会对结果使用一个外部索引排序,而不是按索引次序从表中读取行。
“Range checked for each record (index map:N)”
这个值意味着没有好用的索引,新的索引将在联接的每一行上重新估算。
转载于:https://my.oschina.net/WEguo/blog/1559557