本文实战使用Mysql 8
前一篇文章我们分析了如何通过Explain分析一个sql语句的执行计划和问题点。 那么在分析一个sql之前,我们得要拿到这条sql,我们想要优化这条sql,就需要先去定位到这条有问题或者说查询效率慢的sql,本文学习如何在生产环境下定位慢查询。
慢查询
分析MySQL语句查询性能的方法除了使用 EXPLAIN 输出执行计划,还可以让MySQL记录下查询超过指定时间的语句,我们将超过指定时间的SQL语句查询称为“慢查询”。
当Mysql性能下降时,通过开启慢查询来获得哪条SQL语句造成的响应过慢,进行分析处理。当然开启慢查询会带来CPU损耗与日志记录的IO开销,所以我们要间断性的打开慢查询日志来查看Mysql运行状态。
如何定位慢查询
当发现你服务器数据库返回结果很慢的时候,我们需要去定位数据库具体哪条sql比较慢,这时候需要执行一些命令:
1、临时开启慢查询日志开关
开启才会将执行时间较长的查询通过日志的方式进行记录
mysql>set global slow_query_log = on;
2、临时设置慢查询时间临界点
查询时间高于这个临界点的都会被记录到慢查询日志中【单位/秒】
默认情况下,mysql认为超过10秒才是一个慢查询
mysql>set long_query_time = 1; # 所有执行时间超过1秒的sql都将被记录到慢查询日志文件
3、设置慢查询存储的方式
默认是none,可以设置为4种值,”FILE”、”TABLE”、”FILE,TABLE”、”NONE”,如果是table则慢查询信息会保存到mysql库下的slow_log表中,一般不设置”FILE,TABLE”,因为会徒增不必要的I/O开销
mysql>set globle log_output = file; # 设置慢查询日志输出形式为文件形式
4、查询慢查询日志的开启状态和慢查询日志储存的位置
mysql>show variables like "%slow%"; #查看MySQL慢查询相关设置
5、设置记录所有没有利用索引的查询
性能优化时开启此项,平时不要开启
mysql>set log_queries_not_using_indexes on;
当然,上述设置都是命令临时设置的,可以在mysql的配置文件my.cnf中配置相关属性:
slow_query_log = on -- 开启日志;
slow_query_log_file = /data/f/mysql_slow_cw.log -- 记录日志的log文件; 注意:window上必须写绝对路径,比如 D:/wamp/bin/mysql/mysql5.5.16/data/show-slow.log
long_query_time = 1 -- 慢查询临界时间;
log-queries-not-using-indexes = on -- 表示记录没有使用索引的查询
测试慢查询记录
mysql>select sleep(3);
查看慢查询日志是否记录了上述语句:
root> cd /opt/mysql-8.0.19/data/
root> cat -n VM_0_5_centos-slow.log
像上面这点信息还不够看,我们需要慢查询分析工具mysqldumpslow来帮助我们分析慢查询
使用mysqldumpslow分析慢查询
mysqldumpslow -t 10 VM_0_5_centos-slow.log # 显示出慢查询日志中最慢的10条sql
至此,我们就已经可以定位到具体的慢查询了。
mysqldumpslow工具
mysqldumpslow是mysql安装后就自带的工具,用于分析慢查询日志
Usage: mysqldumpslow [ OPTS... ] [ LOGS... ] -- 后跟参数以及log文件的绝对地址;
-s what to sort by (al, at, ar, c, l, r, t), 'at' is default 排序
al: average lock time 平均锁定时间
ar: average rows sent 平均返回记录数
at: average query time 平均执行时间
c: count 执行计数
l: lock time 锁定时间
r: rows sent 返回记录
t: query time 执行时间
-r reverse the sort order (largest last instead of first) 倒序
-t NUM just show the top n queries 只查看排行上的多少条数据
-a don't abstract all numbers to N and strings to 'S'
-n NUM abstract numbers with at least n digits within names
-g PATTERN grep: only consider stmts that include this string 通过正则表达式匹配我们想要查看的内容
-h HOSTNAME hostname of db server for *-slow.log filename (can be wildcard),
default is '*', i.e. match all
-i NAME name of server instance (if using mysql.server startup script)
-l don't subtract lock time from total time
常用参数命令
mysqldumpslow -s c -t 10 /mysql/data/VM_0_5_centos-slow.log # 取出使用最多的10条慢查询
mysqldumpslow -s t -t 3 /mysql/data/VM_0_5_centos-slow.log # 取出查询时间最慢的3条慢查询
mysqldumpslow -s t -t 10 -g 'left join' /mysql/data/VM_0_5_centos-slow.log # 取出按照时间排序的前10条里面含有左连接的查询语句
返回内容解析
mysqldumpslow分析结果不会显示具体完整的sql语句,只会显示sql的组成结构
**
Count:执行次数
Time:单次执行最长时间(后面跟着的是总执行时间)
Lock:单次锁定最长时间(后面跟着的是总锁定时间)
Rows:返回结果行数
User@Host:对应sql的执行主机和用户
select sleep(N):SQL 的执行内容
Reading mysql slow query log from VM_0_5_centos-slow.log
Count: 3 Time=3.00s (9s) Lock=0.00s (0s) Rows=1.0 (3), root[root]@localhost
select sleep(N)
Count: 1 Time=0.00s (0s) Lock=0.00s (0s) Rows=6.0 (6), root[root]@localhost
show variables like "S"
Count: 1 Time=0.00s (0s) Lock=0.00s (0s) Rows=0.0 (0), root[root]@localhost
set long_query_time = N
我们还可以利用别的工具替代mysqldumpslow(当然,原生的只有mysqldumpslow),如pt-query-digest等,此处不做赘述。