在进行SQL性能优化之前,我们需要学习的就是如何找到这些慢SQL,和我们拿到这些慢SQL后通过什么方式去分析这些SQL的性能如何。
慢SQL定位(慢查询日志)
定位慢SQL相对来说很简单,因为Mysql中已经提供了对应的工鞥,我们只需要开启对应的“慢查询日志”功能,然后稍作配置即可,开启功能有Mysql会把查询时间大于你设置时间的SQL记录下来,并且保存到一个专门的文件中,你只需要查看这个文件内容就可以找到对应查询慢的SQL了,配置了慢查询日志后,它会记录在设定时间范围内的数据查询和数据修改语句。
慢查询日志的配置
在mysql 配置文件中 (不出意外应该在/etc/my.conf),进行下面配置,修改配置后重启mysql生效。
slow_query_log = ON
long_query_time = 5
slow_query_log_file = /opt/soft/mysql/log/slow.log
log_queries_not_using_indexes=on
配置说明:
slow_query_log : 开启或关闭慢查询日志。
slow_query_log_file: 指定生成的慢查询日志路径(未设置则和默认和数据文件放一起)。
long_query_time : 慢查询记录时间阈值,SQL执行超过此时间则会被记录到日志(单位:秒,默认10秒)。
log_queries_not_using_indexes : 是否记录未使用索引的SQL。
可通过下面的命令查看配置是否生效:
show
SQL性能分析(执行计划)
Mysql提供了一个非常实用的命令(explain)来便于我们对SQL进行分析,如下面图所示,只要在SQL语句前加上一个explain关键字,那么我们就会得到一个SQL的执行计划,这个执行计划会告诉我们SQL中表的读取顺序、查询类型、用到了什么索引、使用索引的长度 、扫描了多少条记录等信息,通过执行计划提供的信息我们可以快速定位到哪些地方可以进行优化。
![231158158f05eda0a83dc02405205cae.png](https://i-blog.csdnimg.cn/blog_migrate/11b7af85a8f05b3df4417fb268f71985.jpeg)
执行计划字段详解
1、ID
ID是表示语句执行顺序的标识:
不同的id值,id越大的优先执行;
相同的id值,则由上往下执行,排在上面的语句先执行。
2、select_type
此列主要用于区分查询语句的类型,通过这个列可以区分SQL属于简单的select、联合查询、子查询等。
SIMPLE: 简单的select查询,不包含任何子查询或联合查询。
![aec024c1791f63fccb9f6ba449c6589c.png](https://i-blog.csdnimg.cn/blog_migrate/2ba68d736c71e30c876d45d72767d690.png)
PRIMARY: 主查询,如果有子查询的话,最外层的查询会被标记为PRIMARY。
SUBQUERY: 该语句属于子查询语句。
![24f95d6065936c06e19c33bbc799007c.png](https://i-blog.csdnimg.cn/blog_migrate/d19b2aa6864c7302ec0e5964081b24d8.jpeg)
DERIVED : 生成的临时表的查询语句会被标记为DERIVED 。
![d3e06db4cd2f8b6ec3c9732e6afede32.png](https://i-blog.csdnimg.cn/blog_migrate/f4324018b11d8f61a93badf4735dd4a0.png)
UNION : 标记为UNION类型的查询语句。
UNION RESULT: 从UNION语句中获取结果。
![aa9628af7b48ce9b782c6ebbddedf1dd.png](https://i-blog.csdnimg.cn/blog_migrate/83ef898949a68a33c5aa43fbb8eb30b4.jpeg)
3、table
显示这一行的数据是来源于哪张表的
4、type(重要)
type列是定位SQL性能因素最重要的一个指标,通过type我们可以直观的判断一个SQL的性能的基本情况,type包括以下几种类型的查询system 、const 、eq_ref、ref、Range、Index、All,他们的性能依次从高到底,简单来讲我们进行SQL优化的第一步就是要在type列上定位SQL的性能。
System: 表只有一行记录(日常基本上不会出现)。
Const: 通过索引一次就找到了数据,一般出现在使用了primary key或者unique索引匹配到了数据,匹配的条件是常量(字符串、数字)。
eq_ref: 使用了主键索引,或者非空唯一索引,在表中只有一条记录与索引键相匹配,匹配条件是某个表的列(需要转义替换才能拿到值)。
ref: 非唯一性索引扫描,和eq_ref 不同的是eq_ref 匹配的是唯一索引,ref它返回所有匹配某个单独值的行,它可能会找到多个符合条件的行。
range: 范围数据扫描。
index: 全索引扫描,通过扫描整棵索引树获取到结果。
All: 全表扫描。
Const 和eq_ref 的区别
两个都是在用到了主键索引或唯一索引的情况下出现,不同的是Const 的where 条件是常量,eq_ref 的where 条件是其他表的某个列,需要对这个列进行转义才能拿到匹配条件的值,也可以简单的理解为,eq_ref 一般为关联查询。
5、possible_keys,key,key_len(重要)
possible_keys: 可能使用到的索引 。
Key: 实际使用的索引。如果为空,则说明没有使用索引。
key_len: 使用到的索引key的长度,如果为联合索引则显示已命中的联合索引长度之和(如:联合索引为a+b+c ,如果索引命中了a+b ,那么长度就为a+b的索引长度,通常可以通过key_len 来分析联合索引所命中的情况)。
关于possible_keys 和key的三种关系场景:
possible_keys !=null&& key!=null ,这是正常使用到了索引的情况。
possible_keys !=null&& key==null ,这种情况一般说明通过索引并不能提升多少效率,一般而言是表的数据量很少,或者是索引的字段离散型不高,执行计划发现用索引和扫表差不多。
possible_keys ==null&& key!=null , 这种情况一般为where条件没有命中索引,但是查询的列是索引字段,也就是查询的列命中覆盖索引情况。
6、ref
实际用到的索引是哪个表的列, const代表常量
7、row
扫描的数据行数,一般来说扫描的数据行数越少,性能越高。
8、Extra列(重要)
Extra 可以说是对整个SQL做了一个概括性的总结,包括你用了什么索引、排序方式、使用了临时表包含不适合在其他列显示,但是十分重要的信息
using where;: 使用了where条件。
using index: 使用了覆盖索引。
using filesort : 文件排序,意思就是使用了非索引的字段进行排序(通常这种情况需要优化)。
using index sort : 使用功能索引排序。
using temporary : 使用了临时表(常见于group by、order by)。
using join buffer : 使用了join buffer缓存。