MySQL慢查询

由long_query_time执行时间超过几秒钟并且至少min_examined_row_limit需要检查行的SQL语句组成

Posted by Sunfy on 2021-10-20
Words 2k and Reading Time 7 Minutes
Viewed Times
Viewed Times
Visitors In Total

基本概念

以下基于mysql5.7版本

官方说明:慢查询日志由long_query_time执行时间超过几秒钟并且至少 min_examined_row_limit需要检查行的 SQL 语句组成 。慢查询日志可用于查找需要很长时间执行的查询,因此可以进行优化。但是,检查长而缓慢的查询日志可能是一项耗时的任务。为了使这更容易,您可以使用 mysqldumpslow命令来处理慢查询日志文件并总结其内容。请参阅 第 4.6.8 节,“mysqldumpslow - 总结慢查询日志文件”

获取初始锁的时间不计入执行时间。mysqld会在执行完所有锁后,将语句写入慢查询日志,因此日志顺序可能与执行顺序不同。

MySQL的慢查询,全名是慢查询日志,是MySQL提供的一种日志记录,用来记录MySQL中响应时间超过阈值的语句。

具体的环境中,运行时间超过long_query_time值的SQL语句,则会被记录到慢查询日志中。

long_query_time默认值为10,就是SQL查询时间超过设定值时,会记录当前SQL。

MySQL默认不启动慢查询日志,非调优需要,一般不建议启动该参数,因为开启慢查询后或多或少会对性能有一些影响。

MySQL(5.7)官方对慢查询的说明:https://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html

日志参数

slow_query_log 设置slow_query_log 为 0 以禁用日志或设置为 1 以启用它。

slow_query_log_file 设置 slow_query_log_file以指定日志文件的名称

log_queries_not_using_indexes 要在写入慢查询日志的语句中包含不使用行查找索引的查询,请启用 log_queries_not_using_indexes 系统变量。(即使启用了该变量,服务器也不会记录由于表的行数少于两行而不会从索引的存在中受益的查询。)

log_throttle_queries_not_using_indexes 当记录不使用索引的查询时,慢查询日志可能会快速增长。可以通过设置log_throttle_queries_not_using_indexes 系统变量对这些查询设置速率限制 。默认情况下,此变量为 0,这意味着没有限制。正值对不使用索引的查询的日志记录施加了每分钟限制。第一个这样的查询打开一个 60 秒的窗口,在该窗口中服务器记录查询达到给定的限制,然后抑制其他查询。如果在窗口结束时有被抑制的查询,服务器会记录一个摘要,指示有多少查询以及在这些查询中花费的总时间。当服务器记录下一个不使用索引的查询时,下一个 60 秒窗口开始。

服务器按照以下顺序使用控制参数来决定是否将查询写入慢查询日志:

慢查询日志内容

启用慢查询日志后,服务器将输出写入log_output系统变量指定的任何目的地 。如果启用日志,服务器将打开日志文件并将启动消息写入其中。但是,除非FILE选择了日志目标,否则不会将查询进一步记录到文件中。如果目标是 NONE,则即使启用了慢查询日志,服务器也不会写入任何查询。如果FILE未选择作为输出目的地,则设置日志文件名对日志记录没有影响。

如果启用慢查询日志并FILE选择作为输出目标,则写入日志的每个语句前面都有一行以#字符开头 并具有以下字段(所有字段在一行中):

  • Query_time:duration

    语句执行时间(以秒为单位)。

  • Lock_time:duration

    以秒为单位获取锁的时间。

  • Rows_sent:N

    发送到客户端的行数。

  • Rows_examined:

    服务器层检查的行数(不包括存储引擎内部的任何处理)。

写入慢查询日志文件的每个语句前面都有一个SET 包含时间戳的语句,该时间戳指示记录慢语句的时间(在语句完成执行后发生)。

写入慢查询日志的语句中的密码由服务器重写,不会以纯文本的形式出现。请参阅第 6.1.2.3 节,“密码和日志记录”

参数配置

slow_query_log

使用set global slow_query_log=1开启了慢查询日志只对当前数据库生效,MySQL重启后则会失效。

如果要永久生效,就必须修改配置文件my.cnf(其它系统变量也是如此)。

my.cnf要增加或修改参数slow_query_logslow_query_log_file,如下所示

slow_query_log = 1

slow_query_log_file = /tmp/mysql_slow.log

然后重启MySQL服务器。

slow_query_log_file

这个参数用于指定慢查询日志的存放路径,缺省情况是host_name-slow.log文件

show variables like ‘slow_query_log_file’

long_query_time

mysql源码里是判断大于long_query_time,而非大于等于。

从MySQL 5.1开始,long_query_time开始以微秒记录SQL语句运行时间,之前仅用秒为单位记录。

如果记录到表里面,只会记录整数部分,不会记录微秒部分。

注意:使用命令 set global long_query_time=4修改后,需要重新连接或新开一个会话才能看到修改值。

用show variables like ‘long_query_time’查看是当前会话的变量值。

也可以不用重新连接会话,而是用show global variables like ‘long_query_time’;。

log_output

log_output参数指定日志的存储方式。

log_output=’FILE’表示将日志存入文件,默认值也是’FILE’。

log_output=’TABLE’表示将日志存入数据库,这样日志信息就会被写入到mysql.slow_log表中。

同时也支持两种日志存储方式,配置的时候以逗号隔开即可,如:log_output=’FILE,TABLE’。

日志记录到系统的专用日志表中,要比记录到文件耗费更多的系统资源。

因此对于需要启用慢查询日志,又需要能够获得更高的系统性能,那么建议优先记录到文件。

show variables like ‘%log_output%’;

set global log_output=’TABLE’;

log-queries-not-using-indexes

该系统变量指定未使用索引的查询也被记录到慢查询日志中(可选项)。

如果调优的话,建议开启这个选项。

另外,开启了这个参数,其实使用full index scan的SQL也会被记录到慢查询日志。

show variables like ‘log_queries_not_using_indexes’;

set global log_queries_not_using_indexes=1;

log_slow_admin_statements

这个系统变量表示,是否将慢管理语句例如ANALYZE TABLEALTER TABLE等记入慢查询日志。

show variables like ‘log_slow_admin_statements’;

Slow_queries

如果你想查询有多少条慢查询记录,可以使用Slow_queries系统变量。

show global status like ‘%Slow_queries%’;

另外,还有log_slow_slave_statements--log-short-format 参数,可到MySQL网站了解。

mysqldumpslow

慢查询日志分析工具
mysqldumpslow经常使用的参数:
-s,是order的顺序
——-al 平均锁定时间
——-ar 平均返回记录时间
——-at 平均查询时间(默认)
——-c 计数
——-l 锁定时间
——-r 返回记录
——-t 查询时间
-t,是top n的意思,即为返回前面多少条的数据
-g,后边可以写一个正则匹配模式,大小写不敏感的

比如,得到返回记录集最多的10个SQL。

mysqldumpslow -s r -t 10 /database/mysql/mysql06_slow.log

得到访问次数最多的10个SQL

mysqldumpslow -s c -t 10 /database/mysql/mysql06_slow.log

得到按照时间排序的前10条里面含有左连接的查询语句。

mysqldumpslow -s t -t 10 -g “left join” /database/mysql/mysql06_slow.log

另外建议在使用这些命令时结合 | 和more 使用 ,否则有可能出现刷屏的情况。

mysqldumpslow -s r -t 20 /mysqldata/mysql/mysql06-slow.log | more


Copyright 2021 sunfy.top ALL Rights Reserved

...

...

00:00
00:00