使用MySql慢查日志对有效率问题的SQL进行监控
-- 查看慢查日志是否开启
show variables like 'slow_query_log';
-- 开启慢查日志
set global slow_query_log=on;
-- 查看日志保存位置
show variables like 'slow_query_log_file';
-- 设置日志保存位置
set global slow_query_log_file = '/home/mysql/sql_log/mysql-slow.log';
-- 开启索引记录
set global log_queries_not_using_indexes=on;
-- 设置时间,查询时间超过1s就记录(设置后需要重新连接数据库)
set global long_query_time=1;
为了方便测试,我们可以把超时记录时间设置为0,这样就能保证有日志的记录。
当随便执行一个查询之后,打开log,观察文档最后输出
执行SQL的主机信息
# User@Host: root[root] @ localhost [] Id: 56
SQL的执行信息 执行时长,锁定时长,发送行数,扫描行数
# Query_time: 0.068822 Lock_time: 0.000372 Rows_sent: 997 Rows_examined: 24861
时间时间
SET timestamp=1528166127;
具体的语句
select * from film_list;
虽然可以直接慢查询的数据都记录在了日志中,但是我们直接查看日志是不直观的,需要通过工具来快速的得到一些信息,比如:平均的查询时间,最耗时的查询语句等。
这里就介绍两款常用的日志分析工具
mysqldumpslow是安装mysql时自带的一个工具,我们可以通过mysqldupmslow -h
查看相关的帮助文档,这里我们就列举一些最常用的参数:
Usage: mysqldumpslow [ OPTS... ] [ LOGS... ]
Parse and summarize the MySQL slow query log. Options are
-s ORDER 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
比如我们想查询耗时最长的前十条语句,可以通过
mysqldumpslow -t 10 xxx.log
输出如下:
-- count表示该语句的执行次数
Count: 1 Time=0.07s (0s) Lock=0.00s (0s) Rows=997.0 (997), root[root]@localhost
select * from film_list
pt-query-digest 安装
直接分析慢查日志
pt-query-digest xxx.log
输出的分析内容还是较多的,这里可以参考MySQL慢查询(二) - pt-query-digest详解慢查询日志
在查找到执行较慢的SQL后,我们可以通过explain
来分析sql的执行计划,比如:
explain select customer_id, first_name, last_name from customer;
结果如下:
+—-+————-+———-+——+—————+——+———+——+——+——-+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+—-+————-+———-+——+—————+——+———+——+——+——-+
| 1 | SIMPLE | customer | ALL | NULL | NULL | NULL | NULL | 599 | NULL |
+—-+————-+———-+——+—————+——+———+——+——+——-+
1 row in set (0.00 sec)
Profile是mysql提供可以用来分析当前会话中语句执行的资源消耗情况。可以用于SQL的调优的测量
默认情况下,参数处于关闭状态,并保存最近15次的运行结果
-- 查看是否开启profile
SHOW variables like 'profiling';
-- 开启profile
set profiling=on;
查看profile
show profiles
进一步分析
show profile cpu,block io for query 上一步前面的问题SQL数字号码;
重点需要关注的几个项:
converting HEAP to MyISAM:查询结果太大,内存都不够用了往磁盘上搬了
create tmp table:创建临时表,要注意
Copying to tmp table on disk:把内存临时表复制到磁盘
首先说明一下count(*)和count(1),它们俩在是没有什么不同的。
高性能MySQL——Count(1) OR Count(*)?
MySQL伪科学之count(1)好快
Count()中是可以加条件的:
-- 一条sql同时查出2006和2007年的电影数量
SELECT COUNT(release_year='2006' OR NULL) AS '2006年电影数量', COUNT(release_year='2007' OR NULL) AS '2007年电影数量' FROM film;