MySQL性能优化(四)--Explain执行计划与show Profile分析

  MySQL的Explain执行计划能够用来对Sql语句进行分析,是否进行全表扫描,是否用了索引,或者是sql语句前后执行计划,有没有用临时表等等,由此来进行Sql优化,而show Profile和Explain同样都是用来查看Sql语句分析的,可是形式不同,show Profile用来分析当前会话语句执行的资源消耗状况,能清晰的知道sql执行过程,以及过程当中消耗的时间。mysql

那么我们先来讲一下Explain执行计划sql

这是执行Explain命令后显示的信息,那么不熟悉的就会对此比较陌生,下面来一一讲解每一个列的说明。数据库

1.Explain各字段含义

1.1 id列

id列的编号是select的序列号,表示查询中执行select子句或操做表的顺序缓存

id序列数不一样,若是是子查询的话,则id值越大优先级越高,越先被执行性能优化

id序列数相同,则执行顺序由上到下服务器

id既有相同又有不一样的,视为相同的一组,执行顺序由上到下,不一样的id序列数越大,优先值越高函数

1.2 select_type列

select_type是查询类型,说明查询的种类性能

1.SIMPLE:简单查询,查询不包含子查询和UNION。优化

2.PRIMARY:复杂查询包含含子部分,最外层查询则被标记为PRIMARYspa

3.DERIVED(form型子查询):包含在from子句中的子查询。MySQL会将结果存放在一个临时表中,也称为派生表.

4.UNION:在UNION中第二个随后的select

5.UNION RESULT:从UNION临时表检索结果的select(若是无须要尽可能少写union,由于使用的是临时表,因此不能进行索引优化)

6.DEPENDENT UNION:UNION语句中的第二个SELECT,依赖于外部子查询  (暂时没有写到出现DEPENDENT UNION的sql因此没有示例)

7.SUBQUERY(非form子查询):包含在select中的子查询。

8.DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的子查询

1.3 table列

指的就是当前执行的表

1.4 partitions列

分区表

1.5 type列

type所显示的是查询使用了哪一种类型,即MySQL决定如何查找表中的行。如下是按执行效率排序,优化最好是能优化最高的。

1.system:表只有一行记录(等于系统表),这是const类型的特例,平时不会出现,这个也能够忽略不计。标红的经常使用常常出现的

2.const:MySQL能对查询的某部分进行优化并将其转化为一个常量,const 用于比较primary key 或者unique索引。由于只匹配一行数据因此很快,通常用于主键刷选

3.eq_ref:primary key 或 unique key 索引的全部部分被链接使用,最多只会返回符合条件的记录,这多是const以外最好的链接类型了,简单的select查询不会出现这种type(通常用于关联查询),惟一性索引扫描,对于每一个索引键,表中只有一条记录与之匹配。常见于主键或惟一索引扫描

4.ref:相比eq_ref,不使用惟一索引,而是使用普通索引或者惟一性索引的部分前缀,索引要和某个值相比较,可能会找到多个符合条件的行(非主键非惟一性索引的数据检索)非惟一性索引扫描,返回匹配某个单独值的全部行,本质上也是一种索引访问,它返回全部匹配某个单独值的行,然而,它可能会找到多个符合条件的行,因此他应该属于查找和扫描的混合体。

5.fulltex:

6.ref_or_null:相似ref,可是能够搜索值为null的行

示例: 运行explain select * from film where name = "film1" or name is null;

7.index_merge:多重范围扫描,两表链接的每一个表的链接字段上均有索引存在且索引有序,结果合并在一块儿,适用于作集合的并、交操做。

8.unique_subquery:在子查询中基于惟一索引进行扫描,相似于eq_ref

9.index_ subquery:在子查询中基于除惟一索引以外的索引进行扫描

10.range只检索给定范围的行,使用一个索引来选择行,key列显示使用了哪一个索引,通常在where语句中会出现between,>,<,in等查询,这种范围扫描索引比全表扫描好,由于它只须要开始于索引的某一个点,而结束于另外一点,不用扫描所有索引。Range性能飘忽不定的,主要是看范围给定的多少,数值大,扫描多,数值小,扫描小(范围检索)

11.index:index是基于索引树进行全表扫描,因此一般比ALL快,由于索引文件一般比数据文件小。index是从索引中读取多的,all是从硬盘中读取的

12.ALL:全表扫描,意味着mysql从头至尾去查找所须要的行。一般状况下须要增长索引来进行优化了。不使用索引,顺序扫描,直接读取表上的数据(访问数据文件)

示例: 运行explain select * from actor;

13.INDEX_SCAN: 索引作扫描,是基于索引在索引的叶子节点上找知足条件的数据(不须要访问数据文件)

1.6 possible_key列

这一列显示查询可能使用哪些索引来查找(备选项),不是实际使用的。

1.7 key列

这一列显示mysql实际采用哪一个索引来优化对该表的访问。

1.8 key_len列

这一行显示了MySQL在索引(key)里使用的字节数,可经过该列计算查询中使用的索引的长度,在不损失精确性的状况下,长度越短越好,key_len显示的值为索引字段的最大可能长度,并不是实际使用长度,即key_len是根据表定义计算而得,不是经过表内检索出的

1.9 ref列

这一列显示了在key列记录的索引中,表查找值所用到的列或常量,常见的有:const(常量),func,NULL,字段名(例:film.id

经过type知道主外键关系,经过key主键索引知道ref的哪一个表关联,也知道哪一个字段与之关联对应

1.10 rows列

根据表统计信息及索引选用状况,大体估算出找到所需的记录所须要读取的行数,也就是说,用的越少越好

1.11 filtered列

是一个百分比的值,表明(rows * filtered)/100,这个结果将于前表产生交互

1.12 Extra列

这一列展现的是除解释语句之外的额外信息,也是十分重要的信息

1.distinct:优化distinct操做,在找到第一匹配的元素后即中止找一样值的动做。

2.Using index(效率很好):表示相应的select操做中使用了覆盖索引(Covering index),避免访问了表的数据行,是性能高的表现,若是同时出现using where,代表索引被用来执行索引键值的查找;若是没有同时出现using where,代表索引用来读取数据而非执行查找动做。

同时出现Using Where 代表索引被用来执行索引键值的查找

没有同是出现Using where 代表索引用来读取数据而非执行查找动做

引伸一下,覆盖索引在个人博客 MySQL性能优化(三)--MySQL索引详细介绍(干货满满)有讲到,在这里放一个小小的连接 

https://blog.csdn.net/dfBeautifulLive/article/details/103202803

3.Using where:MySQL服务器将在存储引擎检索行后再进行过滤,就是先读取整行数据,再按where条件进行检查,符合就留下,不符合就丢弃。

4.Using filesort(效率不好):MySQL会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取,MySQL中没法利用索引完成的排序操做称为"文件排序"

5.Using temporary(效率更差):使用了临时表保存中间结果,出现这种状况通常都须要进行优化,MySQL在对查询结果排序时使用临时表。常见于排序order by和分组查询group by。

6.Using join buffer:代表使用了链接缓存,好比说在查询的时候多表join的次数很是多,那么将配置文件中的缓冲区的join buffer调大一些。

7.impossible where:where子句的值老是false,不能用来获取任何元素

2.show Profile SQL分析

SHOW PROFILE 是MySQL提供能够用来分析当前会话语句执行的资源消耗状况,能够用于SQL 的调优测评依据,

SHOW VARIABLES LIKE 'PROFILING'经过这个命令查看参数开关状况

若是是关闭的能够经过这个命令设置开启SET PROFILING = ON;

也能够经过select @@have_profiling命令查看MySQL是否支持profile

若是是profiling是关闭的,经过Set语句开启 set profiling=1;

经过show profiles 查询最近15次运行结果

好比我查询这个sql语句,select count(*) from registered_kj_resourcegroup_type,查询完毕执行show profiles命令,那么我们刚才执行的sql状况就出来了

Query_ID属性:表示从链接上数据库到如今执行的SQL 语句序号

Duration属性:表示执行该SQL 所耗费的时间(S)

Query属性:表示执行的操做

经过show profile for query 285语句可以看到执行过程当中线程的每一个状态和消耗的时间:

注意: Sending data状态表示MySQL线程开始访问数据行并把结果返回给客户端,而不只仅是返回结果给客户端。

           因为在Sending data状态下,MySQL线程每每须要作大量的磁盘读取操做,因此常常是整个查询中耗时最长的状态。

若是对MySQL源码感兴趣能够经过show profile source for query查看SQL解析执行过程当中每一个步骤对应的源码文件、函数名以及具体的源文件行数。

如命令:show profile source for query 310

Source_function属性:函数名称

Source_file属性:源文件

Source_line属性:源文件行数