一、慢查询日志(slow query log)
慢查询日志(slow query log)是MySQL自带的几种日志文件中非常重要的一种日志(另还有错误日志、查询日志、二进制日志。)。
当MySQL性能下降时,通过开启慢查询来获得哪条SQL语句造成的响应过慢,进行分析处理。当然开启慢查询会带来CPU损耗与日志记录的IO开销,所以我们要间断性的打开慢查询日志来查看MySQL运行状态。
慢查询日志可帮助DBA定位可能存在问题的SQL语句,从而进行SQL语句层面的优化。
在默认情况下,MySQL数据库不启动慢查询日志,需要用户手动将log_slow_queries
参数设置为ON。
SHOW VARIABLES LIKE 'log_slow_queries'\G;
SHOW VARIABLES LIKE 'long_query_time'\G;
SHOW VARIABLES LIKE "slow_query_log"\G; # 查看是否开启慢查询日志
SET slow_query_log = ON|OFF; # 开启|关闭慢查询日志
SHOW VARIABLES LIKE "log_output"\G # 查看慢查询日志记录到文件还是表中
SET log_output=TABLE|FILE; # 设置慢查询日志输出到table or files中
SHOW VARIABLES LIKE "slow_query_log_file"\G; # 查看慢查询日志文件路径
SET slow_query_log_file=/usr/local/mysql/data/localhost-slow.log;设置慢查询日志文件路径
SHOW VARIABLES LIKE "long_query_time"\G; # 查看慢查询阀值
SET long_query_time=10; # 设置慢查询阀值为10s
SHOW VARIABLES LIKE "log_queries_not_using_indexes"\G; # 查看是否开启,没有使用索引也记录到慢查询日志中
SET log_queries_not_using_indexes=ON|OFF; # 开启or关闭
SHOW VARIABLES LIKE "log_throttle_queries_not_using_indexes"\G; # 每分钟 允许【因为没有使用索引】而记录到慢查询日志中的sql语句数
SET log_throttle_queries_not_using_indexes = 0; 表示不限制数量,可能会频繁记录,要小心
二、如何分析慢查询日志
mysqldumpslow
该工具是慢查询自带的分析慢查询工具,一般只要安装了mysql,就会有该工具。
Usage: mysqldumpslow [ OPTS... ] [ LOGS... ] -- 后跟参数以及log文件的绝对地址;
-s 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
-r reverse the sort order (largest last instead of first)
-t NUM just show the top n queries
-a don't abstract all numbers to N and strings to 'S'
-n NUM abstract numbers with at least n digits within names
-g PATTERN grep: only consider stmts that include this string
-h HOSTNAME hostname of db server for *-slow.log filename (can be wildcard),
default is '*', i.e. match all
-i NAME name of server instance (if using mysql.server startup script)
-l don't subtract lock time from total time
常见用法
mysqldumpslow -s c -t 10 /var/run/mysqld/mysqld-slow.log # 取出使用最多的10条慢查询
mysqldumpslow -s t -t 3 /var/run/mysqld/mysqld-slow.log # 取出查询时间最慢的3条慢查询
mysqldumpslow -s t -t 10 -g “left join” /database/mysql/slow-log # 得到按照时间排序的前10条里面含有左连接的查询语句
mysqldumpslow -s r -t 10 -g 'left join' /var/run/mysqld/mysqld-slow.log # 按照扫描行数最多的
注意: 使用mysqldumpslow的分析结果不会显示具体完整的sql语句,只会显示sql的组成结构.
假如: SELECT * FROM sms_send WHERE service_id=10 GROUP BY content LIMIT 0, 1000;
mysqldumpslow来显示
Count: 1 Time=1.91s (1s) Lock=0.00s (0s) Rows=1000.0 (1000), vgos_dba[vgos_dba]@[10.130.229.196]
SELECT * FROM sms_send WHERE service_id=N GROUP BY content LIMIT N, N;
由此可以得出哪些SQL语句执行的时间比较长。
pt-query-digest
pt-query-digest是用于分析mysql慢查询的一个工具,它可以分析binlog、General log、slowlog,也可以通过SHOWPROCESSLIST或者通过tcpdump抓取的MySQL协议数据来进行分析。可以把分析结果输出到文件中,分析过程是先对查询语句的条件进行参数化,然后对参数化以后的查询进行分组统计,统计出各查询的执行时间、次数、占比等,可以借助分析结果找出问题进行优化。
pt-query-digest是一个perl脚本,只需下载并赋权即可执行。
这里不做详细介绍。
三、如何进行SQL优化
1、使用explain查询sql的执行计划
explain select comic_id,name,pen_name,cover,last_verify_time from comic;
参数分析:
table:表示属于哪张数据表
type:最重要的参数,表示连接使用了何种类型。从最好到最差的连接类型为const,eq_reg,ref,range,index和ALL。
possible_keys:显示可能应用在这张表中的索引。如果为null,则表示没有可能的索引。
key:实际使用的索引。如果为null,则表示没有使用索引。
key_len:使用的索引的长度,在不损失精确性的情况下,长度越短越好。
ref:表示索引的哪一列被使用了,如果可能的话,是一个常数。
rows:Mysql认为必须检查的用来返回请求数据的行数。
2、count() 和 Max() 的优化方法
(1)优化前,是没有为last_update_time字段建立索引的情况,查询最大的时间戳
(2)优化后,是为last_update_time字段建立索引的情况,查询最大的时间戳
create index update_time on comic(last_update_time);
对比,可以看到,在没有为字段建立索引的情况下,查询时间是11秒多,建立索引之后,查询时间变成0秒了。
所以总结就是,如果经常用于count和max操作的字段,可以为其添加索引。
还有,值得注意的地方是:count() 计算时,count(*)会将这一列中的null值但也算进去,而count(comic_id)则不会将null算进去。
3、子查询的优化
通常情况下,需要把子查询优化为join查询,但在优化时要注意关联键是否有一对多的关系,如果有,是可能会出现重复数据的。所以如果存在一对多关系,则应该使用distinct进行限制。
例如:
select t.id from t where t.id in (select k.kid from k);
优化成:
select distinct t.id from t join k on t.id = k.kid;
参考文章
MySQL优化:定位慢查询的两种方法以及使用explain分析SQL
MySQL定位慢查询步骤
mysql 默认引擎innodb 初探(三)
详解 慢查询 之 mysqldumpslow
Mysql慢查询日志的使用 和 Mysql的优化