MySQL性能优化(四)-- MySQL explain详解

转载地址:http://www.javashuo.com/article/p-kftdkiis-cq.htmljava

MySQL中的explain命令显示了mysql如何使用索引来处理select语句以及链接表。explain显示的信息能够帮助选择更好的索引和写出更优化的查询语句。mysql

1、格式

explain + select 语句;web

例如:explain select * from tb_student;sql

2、5.5和5.7版本explain的区别

5.7以后的版本默认会有 partitions 和 filtered两列,可是5.5版本中是没有的,须要post

使用explain partitions select ……来显示带有partitions 的列,性能

使用explain extended select ……来显示带有filtered的列。优化

本文是基于5.5.54版本的。spa

3、explain的做用

1.描述MySQL如何执行查询操做、执行顺序,使用到的索引,以及MySQL成功返回结果集须要执行的行数。code

2.能够帮助咱们分析 select 语句,让咱们知道查询效率低下的缘由,从而改进咱们的查询,让查询优化器可以更好的工做orm

查询优化器的做用:

1.优化select 语句,分析哪些是常量表达式(例如id=1),以及分析哪些表达式能够直接转换成常量的

2.对where条件进行简化和转换,如去掉无用条件,调整条件结构等

3.读取涉及的表的统计信息,并计算分析(例如返回的行数,索引信息等),最终得出执行计划

4、执行计划(QEP)包含的信息

 

img

 

  1. id:标识符,表示执行顺序
  2. select _type:查询类型
  3. table:输出行所引用的表
  4. partitions:使用的哪一个分区,须要结合表分区才能够看到
  5. type:表示按某种类型来查询,例如按照索引类型查找,按照范围查找。从最好到最差的链接类型为const、eq_reg、ref、range、indexhe和all
  6. possible_keys:可能用到的索引,保存的是索引名称,若是是多个索引的话,用逗号隔开
  7. key:实际用到的索引,保存的是索引名称,若是是多个索引的话,用逗号隔开
  8. key_len:表示本次查询中,所选择的索引长度有多少字节
  9. ref:显示索引的哪一列被使用了,若是可能的话,是一个常数
  10. rows:显示mysql认为执行查询时必需要返回的行数
  11. filtered:经过过滤条件以后对比总数的百分比
  12. extra:额外的信息,例如:using file sort ,using where, using join buffer,using index等

5、执行计划中各个参数的详解

1.id

表示select标识符,同时代表执行顺序,也就是说id是一个查询的序列号,查询序号即为sql语句执行的顺序。

(1)当id值相同时,按从上到下的顺序执行

(2)当id所有不一样时,按id从大到小执行

(3)当id部分不一样时,先执行id大的,id相同的,按从上到下的顺序执行

2.select_type

(1)simple:表示简单的select,没有union和子查询

(2)primary:最外面的查询 或者 主查询,在有子查询的语句中,最外面的select查询就是primary

(3)subquery:子查询

(4)union:union语句的第二个或者说是后面那一个select

(5)union result:union以后的结果

(6)dependent unoin:unoin 中的第二个或随后的 select 查询,依赖于外部查询的结果集

(7)dependent subquery:子查询中的第一个 select 查询,依赖于外部 查询的结果集

(8)derived:衍生表(5.7版本中不存在这一个)

3.table

一般是表名,或者表的别名,或者一个为查询产生临时表的标示符(如派生表、子查询、集合)

4.partitions

使用的哪些分区(对于非分区表值为null),在5.5版本中须要加上explain partitions select .....

5.type

(1)const:表中最多有一个匹配行,const用于比较primary key 或者unique索引。由于只匹配一行数据,因此很快

(2)eq_ref:惟一性索引扫描,对于每一个来自于前面的表的记录,从该表中读取惟一一行

(3)ref:非惟一性索引扫描,对于每一个来自于前面的表的记录,全部匹配的行从这张表取出

(4)ref_or_null:相似于ref,可是能够搜索包含null值的行,例如:select * from student where address='xxx' or address is null,须要在address创建索引。

(5)index_merge:查询语句用到了一张表的多个索引时,mysql会将多个索引合并到一块儿

(6)range:按指定范围(如in、<、>、between and等,可是前提是此字段要创建索引)来检索,很常见。如:select * from student where id < 5,id上要有索引。

(7)index:全”表“扫描,可是是在索引树中扫描,一般比ALL快,由于索引文件一般比数据文件小,index扫描是经过二叉树的方式扫描,而all是扫描物理表。(也就是说虽然all和index都是读全表,但index是从索引中读取的,而all是从硬盘中读的)。例如:select name from student,但name字段上须要创建索引,也就是查询的字段属于索引中的字段。

(8)all:全表扫描,扫描完整的物理表,此时就须要优化了。

6.possible_keys

指出 MySQL 能在该表中可能使用的索引,显示的是索引的名称,多个索引用逗号隔开,若是没有,则为null。

7.key

MySQL决定实际用到的索引,显示的是索引的名称,多个索引用逗号隔开,若是没有,则为null

8.key_len

当用到组合索引的时候判断索引是否彻底用上。

实例:假设student表中有id int,name char(20) DEFAULT NULL,address varchar(20) DEFAULT NULL,remark varchar(20) NOT NULL 字段,创建的索引是 idx_address_remark(在address和remark上创建的组合索引)

查询的sql是:select * from student where address='深圳' and remark='java coder',此时,执行计划中的key_len是 (203+1+2)+ (203+2)= 125,那么这个是怎么得来的呢?

解析:20表示建表的时候 varchar(20) ,3表示utf8字符集占用3个字节,1表示MySQL须要1个字节表示null,2表示变长字段(varchar是变长的)。  

假设drop掉刚刚创建的索引,新建索引 idx_name_address(在name和address上创建组合索引)

查询的sql是:select * from student where name='xbq' and address='深圳',此时,执行计划中的key_len是 (203+1)+ (203+2)= 123,那么这个值是怎么得来的呢?

解析:20表示建表的时候 char(20) ,3表示utf8字符集占用3个字节,1表示MySQL须要1个字节标识null,即 20*3+1,后面的一样的道理。

key_len只计算where条件用到的索引长度,而排序和分组就算用到了索引,也不会计算到key_len中。

计算key_len的公式:

varchr(10)变长字段且容许NULL = 10 * ( character set:utf8=3,gbk=2,latin1=1) + 1(NULL) + 2(变长字段)

varchr(10)变长字段且不容许NULL = 10 *( character set:utf8=3,gbk=2,latin1=1) + 2(变长字段)

char(10)固定字段且容许NULL = 10 * ( character set:utf8=3,gbk=2,latin1=1)+1(NULL)

char(10)固定字段且不容许NULL = 10 * ( character set:utf8=3,gbk=2,latin1=1)

9.ref

显示索引的哪一列被使用了,若是可能的话,是一个常数

10.rows

显示mysql认为执行查询时必需要返回的行数,可结合type和key分析,没有用上索引的状况下,会全表扫描。rows的值越小越好,说明检索的数据少

11.filtered

给出了一个百分比的值,这个百分比值和rows列的值一块儿使用,能够估计出那些将要和执行计划中的前一个表(前一个表就是指id列的值比当前表的id小的表)进行链接的行的数目。

这一列在5.5版本中,须要加上 explain extended select ....。

12.extra

此字段显示一些额外的信息,可是此字段的部分值具备优化的参考意义。

(1)using where:表示查询使用了where 语句来处理结果

(2)using index:表示使用了覆盖索引。这个值重点强调了只须要使用索引就能够知足查询表的要求,不须要直接访问表数据。

(3)using join buffer:这个值强调了在获取链接条件时没有使用索引,而且须要链接缓冲区来存储中间结果。若是出现了这个值,那应该注意,根据查询的具体状况可能须要添加索引来改进性能

(4)using filesort:这是 order by 语句的结果。这多是一个CPU密集型的过程。using filesort表示出现了文件内排序,表示很很差的现象,必需要优化,特别是大表,能够经过选择合适的索引来改进性能,用索引来为查询结果排序。

(5)using temporary:mysql须要建立一张临时表来保存中间结果。 也就是说,须要先把数据放到临时表中,而后从临时表中获取须要的数据。出现这种临时表,也是必须须要优化的地方,特别是数据量大的状况。两个常见的缘由是在来自不一样表的列上使用了distinct,或者使用了不一样的 order by 和 group by 列。

做者:码咖 连接:https://juejin.im/post/5d141528e51d4577565367d0 来源:掘金 著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。
相关文章
相关标签/搜索