EXPLAIN关键字可以模拟优化执行器执行SQL查询语句,从而知道MYSQL是如何处理你的SQL语句。这可以帮你分析你的查询语句或是表结构的性能瓶颈。
id select_type table type possible_keys key key_len ref rows extra
1 SIMPLE mbs ALL 14 Using where
1 SIMPLE mmo eq_ref PRIMARY PRIMARY 4 order_id 1
通过explain命令可以得到:
表的读取顺序
数据读取操作的类型(type)
哪些索引可以使用
哪些数据实际被使用了
表之间的引用
每张表多少行被优化器查询
接下来解释每一个字段的意思:
id :
这一列总是包含一个编号,表示SELECT所属的行。如果在语句中没有子查询或者联合,那么只会有唯一的SELECT,于是每一行在这个列中都将显示一个1.否则内层的SELECT语句一般会顺序编号,对应于其在原始语句的位置。
select_type
这一列显示了对应行是简单还是复杂的SELECT。
SIMPLE意味着查询不包括子查询和UNION,如果查询有任何复杂的子部分,则最外层部分标记为PRIMARY,其他的部分标记如下:
SUBQUERY:
包含在select列表中的子查询中的SELECT(不在from字句中)标记为SUBQUERY。
DERIVED:派生
用来表示包含在FROM子句的子查询中的SELECT,MYSQL会递归执行并将结果放到一个临时表中,
UNION
在union中的第二个和随后的SELECT 被标记为UNION。
UNION RESULT
用来从UNION的匿名临时表检索结果的SELECT被标记为UNION RESULT
table 列
这一列显示了对应行正在访问哪个表。
id select_type table type possible_keys key key_len ref rows extra
type
这一列显示了访问类型--就是mysql决定如何查找表中的行。下面的访问方法,依次从差到优
ALL
全表扫描,通常mysql必须扫描整张表,从头到尾,去找需要的行。
index
这个跟全表扫描一样,只是mysql扫描表时按索引次序进行而不是行。它的主要优点是避免了排序;
最大的缺点是要承担按索引次序读取整个表的开销。如果看到extra列中“USing index”,说明mysql正在使用覆盖索引,它只扫描索引的数据,而不是按索引次序的每一行,它比按索引次序权标扫描的开销要少很多。
range
范围扫描就是一个有限制的索引扫描,它开始于索引里的某一点,返回匹配这个值域的行。这比全索引扫描好一些,因为它用不着遍历全部索引,一般出现在带有范围的条件里面,如between 或在 where字句里带有>的查询。(什么是范围查询)
ref 【reference 参考】
这是一种索引访问(有时也叫索引查找),它返回所有匹配某个单个值的行。然而,它可能会找到多个符合条件的行,因此,它是查找和扫描的混合体。
此类索引访问只有当使用非唯一性索引或者唯一性索引的非唯一性前缀时才会发生(这句有点长~)。把它叫做ref是因为索引要跟某个参考值相比较。这个参考值或者是一个常数,或者是来自多表查询前一个表里的结果值。
ref_or_null 是ref之上的一个变体,它意味着mysql必须在初次查找的结果里进行第二次查找以找出null条目。
eq_ref
使用这种索引查找,mysql知道最多只返回一条符合条件的记录。这种访问方法可以在mysql使用主键或者唯一性索引查找时看到,它会将它们与某个参考值作比较。mysql对于这类访问类型的优化做的非常好,因为它知道无须估计匹配行范围或在找到匹配行后再继续查找。
const ,system
当mysql 能对查询的某部分进行优化并将其转换成一个常量时,它就会使用这些访问类型。
possible_keys 列
这一列显示了查询可以使用哪些索引,这是基于查询放的列和使用比较操作符来判断的。
key 列:
这一列显示了mysql决定采用哪个索引来优化对该表的访问。如果该索引没有出现在possible_keys 列中,那么mysql选用它是处于另外的原因--例如它可能选择了一个覆盖索引,哪怕没有where字句。
换句话说,possible_keys 揭示了哪一个索引能有助于高效的查找,而key显示的是优化采用哪一个索引可以最小化查询成本。
key_len
该列显示了mysql在索引列使用的字节数。索引长度计算方式
假设是char(3)+int(11)
一个char类型的长度为3的字段,在utf8的字符集下总占用 3*3=9个字节
int(11) 占4个字节 索引总长度为 9+4=13个字节
mysql并不总显示一个索引真正用了多少,key_len 列显示了在索引字段中可能的最大长度,而不是表中数据使用的字节数。
ref
这个ref 和type的ref不一样。这个ref显示了表在key列记录的索引中查找值所用的列或常量。
ref列会显示出 const,NuLL 这种字眼。
row列:
这一列是mysql估计为了找到所需的行而要读取的行数。这个数字是内嵌循环关联计划里的循环数目。也就是说它不是imysql认为它要最终从表里读取出来的行数,而是mysql为了找到符合查询的每一点上标准的那些行而必须读取的行的平均数。
通过把所有的rows列的值相乘,可以粗略的估算出整个查询会检查的行数,而不是结果集的行数。
extra列:
这一列包含的是不适合在其他列显示的额外信息。
Using index
此值表示mysql将使用 覆盖索引,以避免访问表。不要把覆盖索引和index访问类型弄混了。
Using where
这意味着mysql服务器将在存储引擎检索后再进行过滤。许多where条件里设计索引中的列,当它读取索引时,就能被存储引擎检验,因此不是所有的带where的字句查询都会显示Using where。有时出现这个就代表一个暗示:查询可受益于不同的索引
Using temporary
这意味着mysql在对查询结果排序时会使用一个临时表。
Using filesort
这意味着mysql在对查询结果排序是会使用一个外部索引排序,而不是按索引次序从表里读取行
Range checked for each record(index map:N)
这个值意味着没有好用的索引,新的索引将在连接的每一行上重新估算。N是显示在possible_keys列中索引的位图,并且是冗余的。
EXPLAIN有两个主要的变种:
1 explain extended
看起来和正常的explain 的行为一样,它会告诉服务器逆向编译 执行计划为一个select语句。然后通过 show warings 查看这个生成的语句,这个语句直接来自执行计划,而不是原SQL,到这点上已经变成了一个数据结构。你可以检测查询优化器到底是如何转化语句的。
它的字段增加了一个filtered
Filtered 显示的是针对表里符合某个条件的记录数的百分比所做的一个悲观估算。
filtered 列给出了一个百分比的值,这个百分比值和rows 列的值相乘,可以估计出那些将要和执行查询计划(QEP) 中的前一个表进行连接的行的数目。前一个表就是指id 列的值比当前表的id 小的表
2 expliain partitions 会显示查询将访问的分区,如果查询时基于分区表的话。