MySQL执行计划分析
列名 | 含义 |
---|---|
id | id列,表示查询中执行select子句或操作表的顺序。 |
select_type | 查询类型,主要是用于区分普通查询、联合查询、子查询等复杂的查询。 |
table | 表明对应行正在访问的是哪个表。 |
partitions | 查询涉及到的分区。 |
type | 访问类型,决定如何查找表中的行。 |
possible_keys | 查询可以使用哪些索引。 |
key | 实际使用的索引,如果为NULL,则没有使用索引。 |
key_len | 索引中使用的字节数,查询中使用的索引的长度(最大可能长度),并非实际使用长度,理论上长度越短越好。 |
ref | 显示索引的那一列被使用。 |
rows | 估算出找到所需行而要读取的行数。 |
filtered | 返回结果的行数占读取行数的百分比,值越大越好。 |
Extra | 额外信息 |
1. id列
id列是一个编号,用于标识SELECT查询的序列号,表示执行SQL查询过程中SELECT子句或操作表的顺序。
如果在SQL中没有子查询或关联查询,那么id列都将显示一个1。否则,内层的SELECT语句一般会顺序编号。
id列分为三种情况:
1)id相同 如下普通查询,没有子查询。
2)id不同 如果存在子查询,id的序号会递增,id值越大优先级越高,越先被执行。
3)id相同又不同 1)、2)两种情况同时存在。id如果相同,认为是一组,从从上往下执行。在所有组中,id值越大,优先级越高,越先执行。
2.select_type列
select_type列表示对应行的查询类型,是简单查询还是复杂查询,主要用于区分普通查询、联合查询、子查询等复杂的查询。
select_type列有如下值:
select_type值 | 说明 |
---|---|
SIMPLE | 简单查询,意味着不包括子查询或UNION。 |
PRIMARY | 查询中包含任何复杂的子部分,最外层查询则被标记为PRIMARY |
SUBQUERY | 在select 或where列表中包含了子查询 |
DERIVED | 表示包含在from子句的子查询中的select,MySQL会递归执行并将结果放到一个临时表中,称其为“派生表”,因为该临时表是从子查询中派生而来的。 |
UNION | 第二个select出现在UNION之后,则被标记为UNION。 |
UNION RESULT | 从UNION表获取结果的select。 |
3.table列
table列表示对应行正在执行的哪张表,指代对应表名,或者该表的别名(如果SQL中定义了别名)。
4.partitions列
查询涉及到的分区。
5.type列
type列指代访问类型,是MySQL决定如何查找表中的行,是SQL查询优化中一个很重要的指标,拥有很多值,依次从最差到最优:
ALL < index < range < index_subquery < unique_subquery < index_merge < ref_or_null < fulltext < ref < eq_ref < const < system
1)ALL
众所周知的全表扫描,表示通过扫描整张表来找到匹配的行,很显然这样的方式查询速度很慢。 这种情况,性能最差,在写SQL时尽量避免此种情况的出现。
在平时写SQL时,避免使用select *,就不难理解了。换言之,是为了避免全表扫描,因为全面扫描是性能最差的。
2)index
全索引扫描,和全表扫描ALL类似,扫描表时按索引次序进行,而不是按行扫描,即:只遍历索引树。 index与ALL虽然都是读全表,但index是从索引中读取,而ALL是从硬盘读取。显然,index性能上优于ALL,合理的添加索引将有助于性能的提升。
3)range
只检索给定范围的行,使用一个索引来选择行。key列显示使用了那个索引。一般就是在where语句中出现了bettween、<、>、in等的查询。这种索引列上的范围扫描比全索引扫描index要好。
举例如下: explain select * from film where film_id between 1 and 10;
4)ref
非唯一性索引扫描,返回匹配某个单独值的所有行。本质是也是一种索引访问,它返回所有匹配某个单独值的行,然而它可能会找到多个符合条件的行,所以它属于查找和扫描的混合体。 此类型只有当使用非唯一索引或者唯一索引的非唯一性前缀时,才会发生。
5)eq_ref
唯一索引扫描。常见于主键或唯一索引扫描。
6)const
通过索引一次就能找到,const用于比较primary key 或者unique索引。因为只需匹配一行数据,所有很快。如果将主键置于where列表中,mysql就能将该查询转换为一个const。 举例如下: show index from film; explain select * from film where film_id = 1;
7)system
表只有一行记录,这是const类型的特例,比较少见,如:系统表。
6. possible_keys列
显示在查询中使用了哪些索引。
7. key列
实际使用的索引,如果为NULL,则没有使用索引。查询中如果使用了覆盖索引,则该索引仅出现在key列中。 possible_keys列表明哪一个索引有助于更高效的查询,而key列表明实际优化采用了哪一个索引可以更加高效。 举例如下: show index from film_actor; explain select actor_id,film_id from film_actor;
8. key_len列
表示索引中使用的字节数,查询中使用的索的长度(最大可能长度),并非实际使用长度,理论上长度越短越好。key_len是根据表定义计算而得的,不是通过表内检索出的。
9. ref列
表示在key列记录的索引中查找值,所用的列或常量const。
10. rows列
估算出找到所需行而要读取的行数。 这个数字是内嵌循环关联计划里的循环数,它并不是最终从表中读取出来的行数,而是MySQL为了找到符合查询的那些行而必须读取行的平均数,只能作为一个相对数来进行衡量。
11. filtered列
返回结果的行数占读取行数的百分比,值越大越好。
12. Extra列
额外信息,但又十分重要。
常见的值如下:
1)Using index 表示SQL中使用了覆盖索引。
2)Using where 许多where条件里是涉及索引中的列,当它读取索引时,就能被存储引擎检验,因此不是所有带·where子句的查询都会显示“Using where”。
3)Using temporary 对查询结果排序时,使用了一个临时表,常见于order by 和group by。
4)Using filesort 对数据使用了一个外部的索引排序,而不是按照表内的索引进行排序读取。也就是说MySQL无法利用索引完成的排序操作成为“文件排序”。