慢查询有什么用?
它能记录下所有执行超过long_query_time时间的SQL语句,帮你找到执行慢的SQL,方便我们对这些SQL进行优化。
开启慢查询
vi /etc/my.cnf
方法一:在服务器上找到mysql的配置文件my.cnf , 然后再mysqld模块里追加一下内容
log_slow_queries = NO 指定是否开启慢查询日志
log_slow_queries = /var/run/mysqld/slow_querys.log 表示输出文件路径 (该参数要被slow_query_log取代,做兼容性保留)
long_query_time = 1 表示超过这个时间的查询都会被记录下来 ,缺省值为10s
log-queries-not-using-indexes 记录下没有使用索引的查询
log-slow-admin-statements
然后重启mysql服务器即可
/etc/init.d/mysql restart
这是通过一下命令看一下慢查询日志的情况:
tail -f /var/run/mysqld/slow_querys.log
方法二:通过修改myssql的全局变量来处理,这样做的好处是,不用重启mysql服务器,登陆到mysql上执行一下sql脚本即可
set global slow_query_log=ON;
set global long_query_time=3;
然后通过一下命令查看是否成功
mysql> show variables like '%slow%';
+------------------------------------+-------------------------------------+
| Variable_name | Value |
+------------------------------------+-------------------------------------+
| log_slow_admin_statements | OFF |
| log_slow_filter | |
| log_slow_rate_limit | 1 |
| log_slow_rate_type | session |
| log_slow_slave_statements | OFF |
| log_slow_sp_statements | ON |
| log_slow_verbosity | |
| max_slowlog_files | 0 |
| max_slowlog_size | 0 |
| slow_launch_time | 1 |
| slow_query_log | ON |
| slow_query_log_always_write_time | 10.000000 |
| slow_query_log_file | /data/logs/mysqld/test-db1-slow.log |
| slow_query_log_timestamp_always | OFF |
| slow_query_log_timestamp_precision | second |
| slow_query_log_use_global_control | |
+------------------------------------+-------------------------------------+
16 rows in set (0.00 sec)
--当前版本
root@localhost[(none)]> show variables like 'version';
+---------------+------------+
| Variable_name | Value |
+---------------+------------+
| version | 5.5.39-log |
+---------------+------------+
存放slow query日志的文件。你必须保证mysql server进程mysqld_safe进程用户对该文件有w权限。
chmod 755 test-db3308-slow.log
chown mysql:jrtm test-db3308-slow.log
查看新生成的 slow log 的内容。
[root@Betty data]
# cat mysql-slow
/usr/local/mysql/bin/mysqld
, Version: 5.6.10-log (Source distribution). started with:
Tcp port: 0 Unix socket: (null)
Time Id Command Argument
[root@Betty data]
#
测试 slow log 。
mysql>
mysql>
select
1;
+
---+
| 1 |
+
---+
| 1 |
+
---+
1 row
in
set
(0.00 sec)
mysql>
mysql>
select
sleep(3);
+
----------+
| sleep(3) |
+
----------+
| 0 |
+
----------+
1 row
in
set
(3.00 sec)
mysql>
mysql>
select
sleep(4);
+
----------+
| sleep(4) |
+
----------+
| 0 |
+
----------+
1 row
in
set
(4.01 sec)
mysql>
mysql>
select
sleep(2);
+
----------+
| sleep(2) |
+
----------+
| 0 |
+
----------+
1 row
in
set
(2.01 sec)
mysql>
mysql>
select
sleep(1);
+
----------+
| sleep(1) |
+
----------+
| 0 |
+
----------+
1 row
in
set
(1.00 sec)
mysql>
select
2;
+
---+
| 2 |
+
---+
| 2 |
+
---+
1 row
in
set
(0.00 sec)
mysql>
查看此时 slow log 的内容。
[root@Betty data]
# cat mysql-slow
/usr/local/mysql/bin/mysqld
, Version: 5.6.10-log (Source distribution). started with:
Tcp port: 0 Unix socket: (null)
Time Id Command Argument
# Time: 130906 12:52:51
# User@Host : root[root] @ localhost [] Id: 1
# Query_time: 3.002864 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0
SET timestamp=1378443171;
select
sleep
(3);
# Time: 130906 12:53:01
# User@Host: root[root] @ localhost [] Id: 1
# Query_time: 4.001943 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0
SET timestamp=1378443181;
select
sleep
(4);
# User@Host: root[root] @ localhost [] Id: 1
# Query_time: 2.002984 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0
SET timestamp=1378443195;
select
sleep
(2);
[root@Betty data]
#
实验:
a. 使用 mysql 自带慢查询日志分析工具 mysqldumpslow 。 mysql官方自带
[root@Betty data]
# mysqldumpslow mysql-slow
Reading mysql slow query log from mysql-slow
Count: 4 Time=3.50s (14s) Lock=0.00s (0s) Rows=1.0 (4), root[root]@localhost
select
sleep
(N)
[root@Betty data]
#
主要功能包括统计不同慢 sql 的
出现次数(Count)
执行耗费的平均时间和累计总耗费时间(Time)
等待锁耗费的时间(Lock)
发送给客户端的行总数(Rows)
扫描的行总数(Rows)
用户以及sql语句本身(抽象了一下格式,比如 limit 1, 20 用 limit N,N 表示)
b. 使用 hackmysql.com 推出的一款日志分析工具 mysqlsla 。
[root@Betty data]
# mysqlsla -lt slow mysql-slow
Report
for
slow logs: mysql-slow
4 queries total, 1 unique
Sorted by
't_sum'
Grand Totals: Time 14 s, Lock 0 s, Rows sent 4, Rows Examined 0
______________________________________________________________________ 001 ___
Count : 4 (100.00%)
Time : 14.009884 s total, 3.502471 s avg, 2.002984 s to 5.002093 s max (100.00%)
Lock Time (s) : 0 total, 0 avg, 0 to 0 max (0.00%)
Rows sent : 1 avg, 1 to 1 max (100.00%)
Rows examined : 0 avg, 0 to 0 max (0.00%)
Database :
Users :
root@localhost : 100.00% (4) of query, 100.00% (4) of all
users
Query abstract:
SET timestamp=N; SELECT
sleep
(N);
Query sample:
SET timestamp=1378443171;
select
sleep
(3);
[root@Betty data]
#
整体来说,功能非常强大。输出的数据报表非常有利于分析慢查询的原因,包括执行频率、数据量、查询消耗等。
格式说明如下:
总查询次数 (queries total),去重后的 sql 数量 (unique)
输出报表的内容排序(sorted by)
最重大的慢 sql 统计信息,包括平均执行时间、等待锁时间、结果行的总数、扫描的行总数。
Count -- sql 的执行次数及占总的 slow log 数量的百分比。
Time -- 执行时间,包括总时间、平均时间、最小、最大时间、时间占到总慢 sql 时间的百分比。
95% of Time -- 去除最快和最慢的 sql,覆盖率占 95% 的 sql 的执行时间。
Lock Time -- 等待锁的时间。
95% of Lock -- 95% 的慢 sql 等待锁时间。
Rows sent -- 结果行统计数量,包括平均、最小、最大数量。
Rows examined -- 扫描的行数量。
Database -- 属于哪个数据库。
Users -- 哪个用户、IP、占到所有用户执行的 sql 百分比。
Query abstract -- 抽象后的 sql 语句。
Query sample -- sql 语句。
除了以上的输出,官方还提供了很多定制化参数,是一款不可多得的好工具。
e. 使用 percona-toolkit 中的 pt-query-digest (在《高性能MySQL》中多次提出,值得使用的工具)。
[root@Betty data]
# pt-query-digest --user=root mysql-slow
# 120ms user time, 10ms system time, 20.21M rss, 68.70M vsz
# Current date: Mon Sep 9 13:21:38 2013
# Hostname: Betty
# Files: mysql-slow
# Overall: 4 total, 1 unique, 0.15 QPS, 0.52x concurrency ________________
# Time range: 2013-09-06 16:07:01 to 16:07:28
# Attribute total min max avg 95% stddev median
# ============ ======= ======= ======= ======= ======= ======= =======
# Exec time 14s 2s 5s 4s 5s 1s 4s
# Lock time 0 0 0 0 0 0 0
# Rows sent 4 1 1 1 1 0 1
# Rows examine 0 0 0 0 0 0 0
# Query size 60 15 15 15 15 0 15
# Profile
# Rank Query ID Response time Calls R/Call V/M Item
# ==== ================== ============== ===== ====== ===== ======
# 1 0xF9A57DD5A41825CA 14.0097 100.0% 4 3.5024 0.36 SELECT
# Query 1: 0.15 QPS, 0.52x concurrency, ID 0xF9A57DD5A41825CA at byte 548
# This item is included in the report because it matches --limit.
# Scores: V/M = 0.36
# Time range: 2013-09-06 16:07:01 to 16:07:28
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 100 4
# Exec time 100 14s 2s 5s 4s 5s 1s 4s
# Lock time 0 0 0 0 0 0 0 0
# Rows sent 100 4 1 1 1 1 0 1
# Rows examine 0 0 0 0 0 0 0 0
# Query size 100 60 15 15 15 15 0 15
# String:
# Hosts localhost
# Users root
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms
# 100ms
# 1s ################################################################
# 10s+
# EXPLAIN /*!50100 PARTITIONS*/
select
sleep
(5)\G
[root@Betty data]
#
分析慢查询日志
方法一:通过查看mysql的慢查询日志分析,比如我们可以tail -f slow_query.log查看里面的内容,字段意义
# Time: 110107 16:22:11
# User@Host: root[root] @ localhost []
# Query_time: 9.869362 Lock_time: 0.000035 Rows_sent: 1 Rows_examined: 6261774
SET timestamp=1294388531;
select count(*) from ep_friends;
第一行,SQL查询执行的时间
第二行,执行SQL查询的连接信息
第三行记录了一些我们比较有用的信息
Query_time SQL执行的时间,越长则越慢
Lock_time 在MySQL服务器阶段(不是在存储引擎阶段)等待表锁时间
Rows_sent 查询返回的行数
Rows_examined 查询检查的行数
方法二:使用mysqldumpslow命令分析,例如
mysqldumpslow -s c -t 10 /tmp/slow-log
这会输出记录次数最多的10条SQL语句,其中:
-s, 是表示按照何种方式排序,c、t、l、r分别是按照记录次数、时间、查询时间、返回的记录数来排序,ac、at、al、ar,表示相应的倒叙; -t, 是top n的意思,即为返回前面多少条的数据; -g, 后边可以写一个正则匹配模式,大小写不敏感的;
比如
/path/mysqldumpslow -s r -t 10 /tmp/slow-log
得到返回记录集最多的10个查询。
/path/mysqldumpslow -s t -t 10 -g “left join” /tmp/slow-log
得到按照时间排序的前10条里面含有左连接的查询语句。
慢查询日志的不足
虽然记录了slow query能够帮助你优化产品。但是MySQL目前版本,还有几大蹩足的地方。
1.MySQL5.0版本, long_query_time时间粒度不够细,最小值为1秒。对于高并发性能的网页脚本而言,1秒出现的意义不大。即出现1秒的查询比较少。直到mysql5.1.21才提供更细粒度的long_query_time设定.
2.不能将服务器执行的所有查询记录到慢速日志中。虽然MySQL普通日志记录了所有查询,但是它们是解析查询之前就记录下来了。这意味着普通日志没办法包含诸如执行时间,锁表时间,检查行数等信息。
3.如果开启了log_queries_not_using_indexes选项,slow query日志会充满过多的垃圾日志记录,这些快且高效的全表扫描查询(表小)会冲掉真正有用的slow queries记录。比如select * from category这样的查询也会被记录下来。开启了log_queries_not_using_indexes选项,slow query日志会充满过多的垃圾日志记录,这些快且高效的全表扫描查询(表小)会冲掉真正有用的slow queries记录。比如select * from category这样的查询也会被记录下来。
相关阅读:
分析MySQL慢查询日志的好工具--mysqlsla http://www.linuxidc.com/Linux/2013-06/86447.htm
MySQL前缀索引导致的慢查询 http://www.linuxidc.com/Linux/2013-05/84520.htm
【体系结构】MySQL 日志文件--慢查询日志 http://www.linuxidc.com/Linux/2013-04/82734.htm
MySQL调优三步曲(慢查询、explain profile) http://www.linuxidc.com/Linux/2012-09/70459.htm