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

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

那么咱们先来说一下Explain执行计划

这是执行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:复杂查询包含含子部分,最外层查询则被标记为PRIMARY

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属性:源文件行数

 

 

 

猜你喜欢

转载自blog.csdn.net/dfBeautifulLive/article/details/103482896