1. id
id列总是包含一组数字,根据它可以识别出select是属于哪一行的。如果查询语句里没有子查询或者联接,那整个输出里就只有一个select,这样一 来,每一行在这个列上都会显示一个1。另外,内层的select语句通常按它们在原始语句的位置顺序来编号。(每个select对应一个id,每个表对应 一行。)
2. select_type
simple
查询里没有子查询或者union。
primary
如果查询里有了任何复杂的子部分,最外层部分就被标记为primary。
subquery
在select的目标里包含了一个子查询(换句话说就是子查询没在from子句里),那就标记为subquery。
derived
值derived用于from子句里有子查询的情况。MySQL会递归执行这些子查询,把结果放在临时表里。在内部,服务器就把它当做一个“衍生表”那样来引用,因为临时表就是源自子查询。
union
如果第2个以及之后的select出现在union里,那就标记为union。第1个select标记为它就像外层查询的一部分那样被执行。如果union包含一个from子句的子查询里,那么,它的第1个select将被标记为derived。
union result
从union临时表获取结果的select被标记为union result。
除这些值外,subquery和union也能作为dependent和uncacheable dependent来标记,这意味着select依赖于外层查询里找到的数据。uncacheable意味着select里有些东西阻止了 item_cache的缓存。(item_cache没有写在文档里,它跟查询缓存不是一回事,尽管它会因一些同样类型的结构而失效,例如rand()函 数。)
3. table
这一列显示了当前行访问的是哪个表。在多数情况下,它的意思很清楚:这是表,或者sql指定的一个别名表。可以从上到下读这一列。看看MySQL联接优化器为这个查询生成的联接次序。
4. type
all
全表扫描,通常意味着MySQL必须扫描整张表,从头到尾,去找到需要的行。(这里也有个例外,例如在查询里使用了limit,或者在extra列里显示使用了distinct或notexists等限定词。)
index
这个跟全表扫描一样,只是MySQL扫描表时按索引次序进行而不是行。它的主要优点是避免了排序;最大的缺点是要承担按索引次序读取整张表的开销。这通常意味着若是随机次序访问行,开销将会非常大。
如果同时看到extra列里有“Using index”,这说明MySQL正在使用一个覆盖索引,它只扫描索引数据,而不是按索引次序的每一行。在开销方面要比按索引次序的全表扫描少很多。
range
范围扫描就是一个有限制的索引扫描,它开始于索引的某一点,返回匹配那值域的行。这比全索引扫描好一些,因为它用不着遍历全部索引。常见的范围扫描就是在where子句里带有between或>的查询。
当MySQL使用一个索引去查找一系列值时,例如in()和or列表,它也会显示为范围扫描。然而,这两者其实是相当不同的访问类型,在性能上有重要的差异。
此类扫描的开销跟索引类型相关。
ref
这是一种索引访问(有时也叫索引查找),它返回所有匹配某个单独值的行。然而,它可能会找到多个符合条件的行,因此,它是查找和扫描的混合体。此类索引访 问只有当使用一个非唯一性索引或者唯一性索引的非唯一性前缀时才会发生。把它叫做ref是因为索引要跟某个参考值相比较。这个参考值或者是一个常数,或者 是来自前一个表里的多表查询的结果值。
ref_or_null是ref之上的一个变体,它意味着MySQL必须进行二次查找,在初次查找的结果里找出null条目。
eq_ref
使用这种索引查找,MySQL最多只返回一条符合条件的记录。这种访问方法会在MySQL使用主键或者唯一索引查找时看到,它会将它们与某个参考值作比较。MySQL对于这类访问类型的优化做得非常好,因为它知道无须估计匹配行的范围,也不用在找到匹配行后再继续查找。
const,system
当MySQL能对某部分进行优化,并转换成一个常量时,它就会使用这些访问类型。举例来说,如果选择了某一行的主键放入where子句里,MySQL就能把这个查询转换为一个常量。然后就可以移除表的联接,更加有效地执行。
Null
这种访问方式意味着MySQL能在优化过程中分解查询语句,在执行环节里,甚至用不着访问表或者索引。从一个索引列里选取最小值可以通过单独查找索引来完成,不需要在执行时访问表。
5. possible_keys
这一列显示了基于查询能够访问的列选用的比较操作类型来决定哪个索引可以被用作查询。这个列表是在优化过程的早期被创建的,因此,有些罗列出来的的索引可能对于后续优化过程是没用的。
6. key
这一列显示了MySQL采用了哪一列索引来优化该表的访问。如果该索引没有出现在possible_keys列,MySQL选用它是出于另外的原因 ————例如,它可能选择了一个覆盖索引,哪怕没有where子句。换句话说,possible_keys揭示了哪一个索引能有助于行查找更加有效,而 key显示的是优化器采用哪一个索引可以最小化查询成本。
7. key_len
该列显示了MySQL在索引里使用的字节数。如果MySQL正在使用的是索引列里的某一个,那就可以用这个值来算出具体是哪一列。要记住MySQL只能使用索引的最左前缀。
key_len列显示的是索引字段的最大可能长度,而不是表内数据使用的真正字节数。换句话说,key_len是根据一个表的定义计算出来的,而不是通过表内数据检索出来的。
8. ref
这列显示了哪些来自上述表里的列或者常量正在被用于查找key列上的值。
9. rows
这一列显示的是MySQL估计的为了找到所需的行而要读取的行数。这个数字是内嵌循环联接计划里的循环数目。也就是说它不是MySQL认为它最终要从表里 读取出来的行数,而是MySQL为了找到符合查询条件的每一点标准上的那些行而必须进行读取的行的平均数。(这个标准包括SQL里给定的条件,以及来自联 接次序上前一个表的当前列。)
根据表的统计信息和索引的选用情况,这个估算可以很精确,在MySQL 5.0及更早的版本里,它不能反映出limit子句。
要记住这个数字是MySQL认为它要检查的行数,不是结果集里的行数。同时也要认识到有很多优化手段,例如联接缓冲区和缓存,都无法影响到行数的显示。MySQL可能不必真的读取所有它估计到的行,它也不知道任何关于操作系统或硬件缓存的信息。
10. filtered
这一列是在MySQL 5.1里新加进去的,当使用explain extended时才会出现。它显示的是针对符合某条件(where子句或联接条件)的记录数的百分比所作的一个悲观估算。如果把rows列和这个百分比 相乘,就能看到MySQL估算的它将和查询计划里前一个表联接的行数。
11. extra
这一列包含的是不适合在其它列显示的额外信息。以下是常见的最重要的值:
“Using index”
该值表示MySQL将使用覆盖索引,以避免访问表。
“Using where”
这意味着MySQL服务器将在从存储引擎收到行后过滤(post-filter)。许多where条件里包含了索引的列,当它(如果它)读取索引的时候, 就能被存储引擎检验,因此,不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个提示:查询可受益于不同的索引。
“Using temporary”
这意味着MySQL在对查询结果排序时会使用一张临时表。
“Using filesort”
这意味着MySQL会对结果使用一个外部索引排序,不是从表里按索引次序读取行。MySQL有两种文件排序算法。任何一种方式都可以在内存或磁盘上进行。explain无法显示MySQL将使用的是哪一种文件排序,也不会告诉你排序会在内存里还是磁盘上进行。
“range checked for each record(index map: N)”
这个值意味着没有好的索引可用,新的索引将在联接的每一行上被重新估算。N是显示在possible_keys列索引的位图,这是一个冗余。
--转自