很多情况下我们需要知道某条SQL语句的性能,都会通过EXPLAIN命令来查看查询优化器是如何执行的。
如何使用
使用EXPLAIN很简单,只需要在执行的SQL前面加上EXPLAIN即可
explain select s.sid sid, s.name studentName, s.age age, c.name className from student_class sc, student s, class c;
执行结果如下:
EXPLAIN中的列
EXPLAIN命令中经常使用到的列有id、
id
id是一个编号,标识SELECT所属的行。如果在语句当中没有子查询或联合查询,那么之后有唯一的SELECT,于是每一行在这个列中都显示1。否则,内层的SELECT语句一般会顺序编号,对应于其在语句中的位置。
SELECT列中子查询
FROM子句中的子查询
UNION查询
注意UNION结果总是放在一个匿名临时表中,之后MySQL将结果读取到临时表外。临时表不在原SQL中出现,因此它的id列是NULL
select_type
select_type列显示了对应行是简单还是复杂SELECT,具体如下:
select_type | 描述 |
---|---|
SIMPLE | 简单查询,不包含任何复杂的子查询(FROM子句中的子查询除外) |
PRIMARY | 复杂查询 |
SUBQUERY | 复杂查询,包含在SELECT列表中的SELECT标记为SUBQUERY |
DERIVED | 复杂查询,包含在FROM子句中的查询 |
UNION | 复杂查询,在UNION查询中的第二个和随后的SELECT被标记为UNION |
UNION RESULT | 复杂查询,用来从UNION的匿名临时表检索结果的SELECT被标记为UNION RESULT |
table
table列显示了对应行在访问哪个表。在通常情况下,它相当明了:它就是那个表,或是该表的别名。当FROM子句中有子查询或有UNION时,table列会变得复杂得多。
- 在FROM子句中有子查询时,table列是<derivedN>,其中N是子查询的id
- 当有UNION时,UNION RESULT的table列中包含一个参与UNION的id列表,如
type
type表示的是访问类型,也就是说MySQL决定如何查找表中的行。下面列表中依次从最差到最优:
type | 描述 |
---|---|
ALL | 全表扫描,从头到尾扫描整个表,效率最差 |
index | 和全表扫描一样,只是MySQL扫描表时按索引次序进行而不是行,主要优点时避免了排序 |
range | 范围扫描就是一个有限制的索引扫描,它开始于索引里的某一点,返回匹配这个值域的行。BETWEEN,IN和OR都属于这类 |
ref | 这是一种索引访问(索引查找),它返回所有匹配某个单个值的行。当使用非唯一性索引或者唯一性索引的非唯一性前缀时才会发生 |
eq_ref | 使用这种索引查找,MySQL知道最多只返回一条符合条件的记录。在使用主键或者唯一性索引查找时发生 |
const、system | 当MySQL能对查询的某部分进行优化并将其转换成一个常量时,它就会使用这种类型。如果通过将某一行的主键放入WHERE子句里的方式来选取次行的主键,MySQL就能帮这个查询转换为一个常量 |
NULL | 意味着MySQL能在优化阶段分解查询语句,在执行阶段甚至用不着再访问表或索引。如从一个索引列里面选取最小值可以通过单独查找索引来完成,不需要在执行时访问表 |
possible_keys
possible_keys表示查询可能使用哪些索引,这是基于查询访问的列和使用的比较操作符来判断的
key
key显示了MySQL决定采用哪个索引来优化对表的访问。如果该索引没有出现在possible_keys列中,那么MySQL可能选择了一个覆盖索引,哪怕没有WHERE子句
key_len
key_len显示了MySQL在索引字段中可能的最大长度。当索引字段是多个时,长度为多个字段长度的和,每个字段的长度是根据定义的表结构中的长度来计算的
ref
ref显示了之前的表在key列记录的索引中查找值所用的列或常量。
rows
rows表示估计为了找到所需的行而要读取的行数。这个值越小越好
filtered
filtered显示的是针对表里符合某个条件的记录数的百分比所做的一个悲观估算。如果你把rows列和这个百分比相乘,就能看到MySQL估算它将和查询计划里面一个表关联的行数。
Extra
Extra包含的是不适合在其他列显示的额外信息。具体如下:
Extra | 描述 |
---|---|
Using index | 意味着MySQL使用覆盖索引,避免访问表 |
Using where | 意味着MySQL服务器将在存储引擎检索行后再进行过滤,并不是所有的WHERE条件查询都有 |
Using temporary | 意味着MySQL在对查询结果排序时使用一个临时表 |
Using filesort | 意味着MySQL会对结果使用一个外部索引排序,而不是按索引次序从表里读取行 |
Range checked for each record (index map: N) | 这个值意味着没有好用的索引,新的索引将在联接的每一行上重新估算。工作中暂时没有遇到 |
以上内容如有描述错误的地方希望大家可以帮忙指出,一起交流学习!