我们经常会遇到MySQL的性能问题,解决办法之一是去定位到低效的SQL语句。
比较常用便是通过以下两种方式定位到执行效率较低的SQL语句:
注:这里使用的MySQL是5.7版本,以下内容都是基于5.7版本
1、慢查询日志:
首先我们应该查看是否已经开启了慢查询日志:
打开MySQL的配置文件my.ini(linux下为my.cnf)并在[mysqld]下添加如下:
slow_query_log = ON
long_query_time=2
slow_query_log_file=\slow.log
上面三条语句意思分别是:
1、开启慢查询;
2、将所有执行时间超过long_query_time设置值的SQL语句记录到日志
3、指定慢查询日志位置
log_query_time现如今已经可以精确到微妙级别,也就是现在是以微秒级别记录数据,但是如果我们把日志输出方式记录到表的话,则慢查询是只能精确到秒级别的,参数log_output则是定义日志存储方式的,当我们定义为log_output='TABLE'时候则会把日志信息写入到mysql.slow_log表中。
这里需要注意,在默认情况下,有两类语句类型不会被记录到慢查询日志中:管理语句和不使用索引进行查询的语句,这里的管理语句包括ALTER TABLE,ANALYZE TABLE,CHECK TABLE,CREATE INDEX,DROP INDEX,OPTIMIZE TABLE 和REPAIR TABLE,如果我们需要监控这两类SQL语句,可以分别通过参数--log-slow-admin-statements和log_queries_not_using_indexes来控制。
然后我们在管理员权限上重启mysql服务:
为了方便测试,现在有一张表里面被灌入4千5百万多条数据,除了主键索引之外没有任何其他索引
我们上面是将阈值设定为2秒,这里查询用了54秒多,所以被记录到慢查询日志里面
以上日志主要字段Query_time1是查询耗时;
Lock_time:锁占用时间
Row_sent:返回给客户端记录数
Row_examined:检查表记录数
我们可以把慢查询设置成微妙级别的,只需要将long_quert_time设置为如下形式:
我们上面也已经说了,慢查询记录时候有两类语句是不会记录进去的,其中一个是不使用索引的查询,而如果想要把这个也记录进去则需要使用到log_queries_not_using_indexes变量了:
set global log_queries_not_using_indexes=1;
而分析慢查询的工具也有很多,mysql自带的mysqldumpslow或者是第三方工具pt-query-digest都可以,这里不去说明他们的使用了。
2、命令SHOW PROCEESSLIST
慢查询日志是只有在查询结束之后才会记录,但是如果在执行过程中我们可以使用这条命令去定位问题。
使用这条命令,如果你有超级权限,那么你将会看到所有的线程,否则你只能看到登陆的用户或者是自己的线程
id是用户登录mysql时候,系统分配的connectin_id,可以select connection_id()查看
user:当前用户名
host:ip+端口
db:正在使用哪一个数据库
command:显示用户正在执行的操作,一般为sleep,query,connect等
time:显示上面状态持续时间
state:显示当前连接的sql语句状态
info:显示当前这条SQL语句