文章目录

      • (1)id列
      • (2)select_type列
      • (3)table列
      • (4)type列
      • (5)possibIe_keys列
      • (6)key列
      • (7)key_len列
      • (8)ref列
      • (9)rows列
      • (10)fiItered列
      • (11)Extra列

EXPLAIN 命令是查看查询优化器如何决定执行 查询的主要方法。这个功能有局限性,并不总会说出真相,但它的输出 是可以获取的最好信息,值得花时间了解,因为可以学习到查询是如何 执行的。学会解释EXPLAIN 将帮助你了解MySQL优化器是如何工作的

在查询中每个表在输出中只有一行。如果查询是两个表的联接,那 么输出中将有两行。别名表单算为一个表,因此,如果把一个表与自己 联接,输出中也会有两行。

(1)id列

这一列总是包含一个编号,标识SELECT 所属的行。如果当前查询不包含子查询,那么每一行在这个 列中都将显示一个1。

MySQL将SELECT 查询分为简单和复杂类型,复杂类型可分成三大 类:简单子查询、所谓的派生表(在FROM子句中的子查询),以 及UNION 查询
【简单子查询】

EXPLAIN SELECT a.user_id
	, (
		SELECT MAX(b.pay_time) AS pay_time
		FROM t_order b
		WHERE b.user_id = a.user_id
	)
FROM t_user a;


【UNION 查询】

EXPLAIN SELECT  1  UNION  SELECT  1


注意UNION 结果输出中的额外行。UNION 结果总是放在一个匿名临 时表中,之后MySQL将结果读取到临时表外。临时表并不在原SQL中出 现,因此它的id列是NULL

(2)select_type列

这一列表示当前对应行的查询是简单还是复杂查询,其中简单查询如下所示SIMPLE。

SIMPLE 值意味着查询不包括子查询和 UNION 。如果查询有任何复杂的子部分,则最外层部分标记为PRIMARY ,其他部分标记如下
【SUBQUERY】
SUBQUERY包含在SELECT 列表中的子查询中的SELECT (换句话说,不 在FROM 子句中)标记为SUBQUERY 。

【DERIVED】
DERIVED 值用来表示包含在FROM 子句的子查询中的SELECT , MySQL会递归执行并将结果放到一个临时表中。服务器内部称 其“派生表”,因为该临时表是从子查询中派生来的。

 EXPLAIN SELECT * FROM ( SELECT * FROM products) t WHERE id=1 ; 

【UNION 】
在UNION 中的第二个和随后的SELECT 被标记为UNION 。第一 个SELECT 被标记就好像它以部分外查询来执行。这就是之前的例 子中在UNION 中的第一个SELECT 显示为PRIMARY 的原因。如果 UNION 被FROM 子句中的子查询包含,那么它的第一个SELECT 会被 标记为DERIVED 。
UNION RESULT 用来从UNION 的匿名临时表检索结果的SELECT 被标记为UNION RESULT 。

(3)table列

对应的是就是查询的表名或者表的别名

(4)type列

数据的访问类型。即MySQL如何查找表中的行。

注意: 下面是最重要的访问方法,依次从最差到最优

【All】
全表扫描,通常意味着MySQL必须扫描整张表, 从头到尾,去找到需要的行。(这里也有个例外,例如在查询里使 用了LIMIT ,或者在Extra 列中显示“Using distinct/not exists”。)

【index】
index 这个跟全表扫描一样,只是MySQL扫描表时按索引次序进行 而不是行。它的主要优点是避免了排序;最大的缺点是要承担按索 引次序读取整个表的开销。这通常意味着若是按随机次序访问行, 开销将会非常大。

如果在Extra 列中看到“Using index”,说明MySQL正在使用覆盖索引,它只扫描索引的数据,而不是按索引次序的每一行。它比 按索引次序全表扫描的开销要少很多。

【range】
range 范围扫描就是一个有限制的索引扫描,它开始于索引里的某一 点,返回匹配这个值域的行。这比全索引扫描好一些,因为它用不 着遍历全部索引。显而易见的范围扫描是带有BETWEEN 或在WHERE 子句里带有>的查询。 当MySQL使用索引去查找一系列值时,例如IN() 和OR 列表, 也会显示为范围扫描。然而,这两者其实是相当不同的访问类型, 在性能上有重要的差异。 此类扫描的开销跟索引类型相当。

【ref 】
ref 这是一种索引访问(有时也叫做索引查找),它返回所有匹配 某个单个值的行。然而,它可能会找到多个符合条件的行,因此, 它是查找和扫描的混合体。此类索引访问只有当使用非唯一性索引 或者唯一性索引的非唯一性前缀时才会发生。把它叫做ref 是因为 索引要跟某个参考值相比较。这个参考值或者是一个常数,或者是 来自多表查询前一个表里的结果值。 ref_or_null 是ref 之上的一个变体,它意味着MySQL必须在 初次查找的结果里进行第二次查找以找出NULL条目。

【eq_ref 】
eq_ref 使用这种索引查找,MySQL知道最多只返回一条符合条件的 记录。这种访问方法可以在MySQL使用主键或者唯一性索引查找 时看到,它会将它们与某个参考值做比较。MySQL对于这类访问 类型的优化做得非常好,因为它知道无须估计匹配行的范围或在找 到匹配行后再继续查找。

【const, system 】
当MySQL能对查询的某部分进行优化并将其转换成一个常量 时,它就会使用这些访问类型。举例来说,如果你通过将某一行的 主键放入WHERE 子句里的方式来选取此行的主键,MySQL 就能把 这个查询转换为一个常量。然后就可以高效地将表从联接执行中移 除。

【NULL】

这种访问方式意味着MySQL能在优化阶段分解查询语句,在 执行阶段甚至用不着再访问表或者索引。例如,从一个索引列里选 取最小值可以通过单独查找索引来完成,不需要在执行时访问表。

(5)possibIe_keys列

这一列显示了查询可以使用哪些索引,这是基于查询访问的列和使 用的比较操作符来判断的。这个列表是在优化过程的早期创建的,因此 有些罗列出来的索引可能对于后续优化过程是没用的。

(6)key列

这一列显示了MySQL 决定采用哪个索引来优化对该表的访问。如 果该索引没有出现在possible_keys 列中,那么MySQL选用它是出于另 外的原因——例如,它可能选择了一个覆盖索引,哪怕没有WHERE 子 句

换句话说,possible_keys 揭示了哪一个索引能有助于高效地行查 找,而key显示的是优化采用哪一个索引可以最小化查询成本

(7)key_len列

该列显示了MySQL在索引里使用的字节数。如果MySQL正在使用 的只是索引里的某些列,那么就可以用这个值来算出具体是哪些列。

当我们计算列的使用情况时,务必把字符列中的字符集也考虑进去。

(8)ref列

这一列显示了之前的表在key 列记录的索引中查找值所用的列或常量

(9)rows列

这一列是MySQL估计为了找到所需的行而要读取的行数。这个数 字是内嵌循环关联计划里的循环数目。也就是说它不是MySQL认为它 最终要从表里读取出来的行数,而是MySQL为了找到符合查询的每一 点上标准的那些行而必须读取的行的平均数。

要记住这个数字是MySQL认为它要检查的行数,而不是结果集里 的行数。同时也要认识到有很多优化手段,例如关联缓冲区和缓存,无 法影响到行数的显示。MySQL可能不必真的读所有它估计到的行,它 也不知道任何关于操作系统或硬件缓存的信息。

(10)fiItered列

它显示的是针对表里符合某个条件(WHERE 子句或联接条件)的 记录数的百分比所做的一个悲观估算。
如果你把rows 列和这个百分比 相乘,就能看到MySQL估算它将和查询计划里前一个表关联的行数。

(11)Extra列

这一列包含的是不适合在其他列显示的额外信息。MySQL用户手 册里记录了大多数可以在这里出现的值。
“Using index”:此值表示MySQL将使用覆盖索引,以避免访问表。不要把覆 盖索引和index 访问类型弄混了。

“Using where”:这意味着MySQL服务器将在存储引擎检索行后再进行过滤。 许多WHERE 条件里涉及索引中的列,当(并且如果)它读取索引 时,就能被存储引擎检验,因此不是所有带WHERE 子句的查询都会 显示“Using where”。有时“Using where”的出现就是一个暗示:查询 可受益于不同的索引。

“Using temporary” 这意味着MySQL在对查询结果排序时会使用一个临时表。

“Using filesort” 这意味着MySQL会对结果使用一个外部索引排序,而不是按 索引次序从表里读取行。MySQL有两种文件排序算法,你可以在 第6章读到相关内容。两种方式都可以在内存或磁盘上完 成。EXPLAIN 不会告诉你MySQL将使用哪一种文件排序,也不会告 诉你排序会在内存里还是磁盘上完成。

“Range checked for each record (index map: N) ” 这个值意味着没有好用的索引,新的索引将在联接的每一行上 重新估算。 N 是显示在possible_keys 列中素引的位图,并且是冗 余的。

更多推荐

MySQL进阶——EXPLAIN详解