学习解释EXPLAIN将帮助你了解MySQL优化器是如何工作的。要使用EXPLAIN,只需要在查询的SELECT关键字之前加上EXPLIAN这个词,MySQL会在查询上设置一个标志。当执行一个查询时,这个标志会使其返回在执行计划中每一步的信息,而不是执行它。增加EXPLAIN时在查询在FROM子句中包括子查询的情况下,会执行子查询。
EXPLAIN的一些限制
- explain不会告诉触发器、存储过程或UDF如何影响查询的
- explain不支持存储过程,尽管可以手动抽取查询并单独地进行EXPLAIN操作
- explain不会告诉你MySQL在查询计划中所做的的特定优化
- explain不会显示关于查询的计划的所有信息
- explain并不区分具有相同名字的事物
EXPLAIN中的列总是10个列,分别是id、 select_type、 table、 type、 possible_keys、 key、key_len、 ref、 rows、 Extra,只有EXPLAIN EXTENDED在MySQL5.1增加了一个filtered列,EXPLAIN PARTITIONS 增加了一个Partitions列)。
id列
这一列总是包含一个编号,标示SELECT所属的行,如果在语句中没有子查询或者联合,那么只会有唯一的SELECT。
EXPLAIN SELECT * FROM MYTABLE;
EXPLAIN SELECT (SELECT 1 FORM MYTABLE1 LIMIT 1 ) FROM MYTABLE2;
MySQL把SELECT查询分为简单和复杂查询,复杂类型可分为三类:简单子查询、所谓的派生表、以及UNION查询。上面的那条查询语句就是简单子查询,FROM子句中的子查询就是所谓的派生表。
SELECT ctime FROM (SELECT ctime FROM `a `) AS der;
UNION的结果总是放在一个匿名的临时表中,之后MySQL将结果读取到临时表外。
SELECT 1 UNION 1 ALL SELECT 1;
Select_type列
这一列显示了对应行是简单还是复杂SELECT。如果是简单查询,则显示SIMPLE值,如果是复杂的查询,最外层部分均标记为PAIMARY。接下来根据复杂查询的种类,简单子查询显示SUBQUERY,如果是派生表显示DERIVED,如果是UNION查询显示UNION。
table列
这一列显示了对应行在访问哪一个表。可以在这一列中从上往下观察MySQL的关联优化器为查询选择的关联顺序。
Type列
表示访问类型,就是MySQL决定如何查找表中的行,下面的访问方法依次从最差到最优。
·ALL
- 最差的方法,利用全表扫描
- Index
这个跟全表扫描一样,只是MySQL扫描表时按索引次序进行而不是行。他的主要优点是避免了排序。最大的缺点是要承担按索引次序读取整张表的开销。意味着随机次序访问行,开销很大。如果在Extra列中看到“Using index”,说明使用的是覆盖索引。
- Range
范围扫描就是一个有限制的索引扫描,开始于索引里的某一点,返回匹配这个值域的行。比全索引扫描好一点,不用遍历全部索引,当MySQL使用索引去查找一系列的值时,例如IN()和OR列表,也会显示为范围查询。
- Ref
这是一种索引访问,返回所有匹配某个单个值的行,它是查找和扫描的混合体,此类索引访问只有当使用了非唯一性索引或者唯一性索引的非唯一性前缀才会发生。
- eq_ref
使用这种索引查找,MySQL知道最多会只会返回一条符合条件的记录。这种访问方法只会在MySQL使用主键或者唯一性索引查找才会看到。
- Const, system
当MySQL能够对查询的某一部分进行优化并将其转换为一个常量时,就会使用这些访问类型。
- NULL
这种方式意味着MySQL能够在优化阶段分解查询语句,在执行阶段甚至不用再访问表或者索引。
Possible_key列
这一列显示了查询可以使用那些索引,这是基于查询访问的列和使用的比较操作符来判断的。
Key列
这一列显示了MySQL决定使用哪个索引来优化对表的访问,如果该索引没有出现在possible_key列中,说明MySQL选择了覆盖索引
Key_len列
该列显示了MySQL在索引中使用的字节数。如果MySQL正在使用的只是索引里的某些列,就可以利用这个值来算出具体是那些列。
Ref列
显示了之前的表在key列记录的索引中查找值所用的列或者常量。
Rows列
这一列是MySQL为了找到所需的行而要读取的行数。他不是MySQL认为它最终要从表中读取的行数,而是MySQL为了找到符合查询的每一个点上标准的那些行而必须读取的行的平均数。
Extra列
这一列包含的是不适合显示在其他列的额外信息,例如下图表示使用覆盖索引