慢查询分析
mysql慢查询日志开启
mysql 提供一种慢查询日志记录,用于记录响应时间超过阈值的SQL语句(默认是关闭的)。
1 | 临时开启: |
1 | 永久开启,在my.cnf中加入配置: |
排查慢查询
查询慢查询数量
一般来说,每分钟慢查询在个位数是正常的,如果量比较大,就可能存在问题
慢查询的数量保存在mysql库里面的slow_log表。select * from slow_log where start_time > '2021-11-01 00:00:00'
查看当前进行的查询状态
查看当前系统的查询,可以试用show processlist,如果要做条件查询,则可以直接查询information_schema库里面的processlist表
查看当前所有process:select * from information_schema.processlist
查看当前正在进行的查询并按照已经执行时间倒排select * from information_schema.processlist where info is not null order by time desc
一般来讲,一条查询的执行速度很快,所以被我们抓到info不是null的数量不会太多,一般几条,如果一次查到info不是null的数量较多,可能就是系统出了问题。
问题定位与解决
当察觉系统变慢时,查询慢查询数量以及查看processlist,看慢查询数量是不是飙升,processlist中是不是很多lock状态,或者执行了很长时间的查询。为了尽快恢复系统的正常运行,直接kill掉那些lock和执行较长时间的查询,但这是临时的办法,我们还要找到慢查询的原因。mysql> kill id
在慢查询表里有几个比较重要的指标:
- start_time 开始时间,通过这个参数配合系统出现问题的时间,定位是哪些查询造成的
- query_time 查询时间
- rows_sent 发送的结果数
- rows_examined 查询扫过的行数,通过这个参数基本可以告诉我们,那个是大查询
在实际操作中,需要把row_examined较大的查询拿出来做优化,添加索引,修改语句等来彻底解决问题。
explain分析SQL执行状态
explain显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。
使用方法,在select语句前加上explain就可以了,例如下:
explain select c.title, cc.content form comment_content cc, comment c where cc.id=c.id
explain列解释
table列:显示这一行的数据是关于哪张表的
type列:这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、index和ALL
possible_keys 列:显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句
key列:实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MYSQL会选择优化不足的索引。这种情况下,可以在SELECT语句 中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MYSQL忽略索引
key_len列:使用的索引的长度。在不损失精确性的情况下,长度越短越好
ref列:显示索引的哪一列被使用了,如果可能的话,是一个常数
rows列:MYSQL认为必须检查的用来返回请求数据的行数
Extra列:关于MYSQL如何解析查询的额外信息。
SQL优化建议
- 优化索引,最简单粗暴的办法,给查询语句添加复合索引,但不是最好的方式
- 将大表拆成小的汇总表
- 避免在大表上的group by,order by,offset 操作,除非你知道如何优化的前提下
- SQL WHERE查询条件,尽量按照添加的索引顺序来写