侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

MySQL慢查询优化之慢查询日志分析的实例教程

数据库  /  管理员 发布于 6年前   216

数据库响应慢问题最多的就是查询了。现在大部分数据库都提供了性能分析的帮助手段。例如Oracle中会帮你直接找出慢的语句,并且提供优化方案。在MySQL中就要自己开启慢日志记录加以分析(记录可以保存在表或者文件中,默认是保存在文件中,我们系统使用的就是默认方式)。

先看看MySQL慢查询日志里面的记录长什么样的:

Time         Id Command  Argument# Time: 141010 9:33:57# User@Host: root[root] @ localhost [] Id:   1# Query_time: 0.000342 Lock_time: 0.000142 Rows_sent: 3 Rows_examined: 3use test;SET timestamp=1412904837;select * from t;

这个日志应该很好理解了,第一个#记录时间戳,第二个#记录执行命令的用户和地址信息,第三个#记录执行查询的时间、锁的时间、返回行数、被扫描的行数。接着后面记录真正执行的SQL语句。还可以通过以下命令看看cvs存储格式每个字段意义。

SHOW CREATE TABLE mysql.slow_log;

接下来说说如何获取和分析慢日志吧。

查看MySQL慢日志参数

进入启动好的MySQL,执行以下命令

mysql> show variables like '%slow_query%';
+---------------------------+----------------------------------------+| Variable_name       | Value     |+---------------------------+----------------------------------------+| slow_query_log      | OFF      || slow_query_log_file    | /usr/local/mysql/data/cloudlu-slow.log |+---------------------------+----------------------------------------+

这里告诉我们慢日志的日志存放位置,慢日志是否有开启。
那么什么样的查询需要被日志呢?在MySQL中, 没有index的查询 以及 超过指定时间同时超过指定扫描行数的查询 需要记录在慢日志查询里面。

那么它们的参数又是怎么查看的呢?

没有index的查询记录开关

mysql> show global variables like '%indexes%';
+----------------------------------------+-------+| Variable_name | Value |+----------------------------------------+-------+| log_queries_not_using_indexes     | OFF  || log_throttle_queries_not_using_indexes | 0   |+----------------------------------------+-------+

第一个参数 表示是否开启记录没有index的查询,第二个

参数用来做日志记录的流量控制,一分钟可以记录多少条,默认0是表示不限制。

超过指定时长的查询开关

mysql> show global variables like '%long_query%';
+-----------------+-----------+| Variable_name  | Value   |+-----------------+-----------+| long_query_time | 10.000000 |+-----------------+-----------+1 row in set (0.00 sec)

就一个参数指定超过多少时长的查询需要被记录

超过指定行数的扫描查询开关

mysql> show variables like '%min_examined_row_limit%';
+------------------------+-------+| Variable_name     | Value |+------------------------+-------+| min_examined_row_limit | 0   |+------------------------+-------+1 row in set (0.00 sec)

默认是0,代表不现在扫描行数

设置开启MySQL慢日志参数

进入MySQL,输入以下命令或者在MySQL的启动配置文件里面修改或者给MySQL添加启动参数,进入MySQL后的修改如下:

set global long_query_time=0.1;set global log_queries_not_using_indexes=on;set global slow_query_log = on;

这里要斟酌的有2点,第一是超过什么时长的日志是有问题的,这个由系统需求来决定。第二是没有使用indexes的日志每分钟要记录多少条,要防止日志太多对性能产生影响。

在实际的日志分析中,通常慢日志的log数量不少,同时相同的查询被记录的条数也会很多,这里就需要如何从慢日志查询中找到最有问题,最需要优化的日志。在这方面,有很多分析工具,最基本的分析工具就是MySQL自带的mysqldumpslow,mysqldumpslow(Perl脚本)的输出示例:

[root@cloudlu bin]# ./mysqldumpslow -s t -t 1 /usr/local/mysql/data/cloudlu-slow.log 

 

Reading mysql slow query log from /usr/local/mysql/data/cloudlu-slow.log Count: 1 Time=0.00s (0s) Lock=0.00s (0s) Rows=3.0 (3), root[root]@localhost  select * from t 

一看就非常清楚,它的输出主要 统计不同慢sql的出现次数(Count 1),执行最长时间(Time 0.00s),累计总耗费时间(Time 0s),等待锁的时间(Lock 0.00s),等待锁的总时间(Lock 0s),发送给客户端的行总数(Rows 3.0),扫描的行总数(Rows 3),用户(root)以及sql语句本身。它最常用的参数包括:

  • -s 排序选项:c 查询次数 r 返回记录行数 t 查询时间
  • -t n:显示top n条查询

对于一般的分析已经差不多了,不过对于百分比等等数据mysqldumpslow就不够完善了。所以世界上多了很多各种MySQL慢日志分析工具,比较优秀的有mysqlsla(Perl脚本)和pt-query-digest(Perl脚本),可以提供Count, sql的执行次数及占总的slow log数量的百分比,Time, 执行时间, 包括总时间, 平均时间, 最小, 最大时间, 时间占到总慢sql时间的百分比,95% of Time, 去除最快和最慢的sql, 覆盖率占95%的sql的执行时间,Lock Time, 等待锁的时间,95% of Lock , 95%的慢sql等待锁时间,Rows sent, 结果行统计数量, 包括平均, 最小, 最大数量,Rows examined, 扫描的行数量,还可以生成表报,存储分析结果。这里就不一一介绍了。

通过这些慢日志分析软件定位到了慢查询语句就已经完成了SQL优化的一大半。接下来通过在MySQL中执行explain或者desc命令查看慢查询语句,可以看出为什么SQL查询慢。

mysql> explain select * from test.t \G 
*************************** 1. row ***************************       id: 1  select_type: SIMPLE     table: t      type: ALL possible_keys: NULL      key: NULL    key_len: NULL      ref: NULL      rows: 2     Extra: NULL 1 row in set (0.00 sec) 

它的输出格式细节可以关注MySQL explain format,在输出中最要注意的是:
1. type:ALL是效率最差,最要注意的

2. key:是否有使用Key,key长度如何

3. Extra:最好不要出现filesort以及temporary,最主要是要关注在orderby和groupby。


Note: SQL优化是个很复杂的过程,有可能出现拆东墙补西墙的情况:比如给数据库表加入了索引之后,确实查询快了,可是存储空间加多了,插入删除操作耗时也增加了,如果在一个写多读少的系统中,执行这种优化可能会起到反效果。所以优化完之后千万不能大意,要持续监控系统,防止出现引入新瓶颈的情况。


  • 上一条:
    MySQL中基本的多表连接查询教程
    下一条:
    MySQL中Innodb的事务隔离级别和锁的关系的讲解教程
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 分库分表的目的、优缺点及具体实现方式介绍(0个评论)
    • DevDB - 在 VS 代码中直接访问数据库(0个评论)
    • 在ubuntu系统中实现mysql数据存储目录迁移流程步骤(0个评论)
    • 在mysql中使用存储过程批量新增测试数据流程步骤(0个评论)
    • php+mysql数据库批量根据条件快速更新、连表更新sql实现(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2017-06
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-01
    • 2018-05
    • 2018-10
    • 2018-11
    • 2020-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2021-02
    • 2021-04
    • 2021-07
    • 2021-08
    • 2021-11
    • 2021-12
    • 2022-02
    • 2022-03
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-07
    • 2023-08
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-03
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客