MySQL如何快速定位慢SQL的实战

目录
  • 开启慢查询日志
  • 系统变量
  • 修改配置文件
  • 设置全局变量
  • 分析慢查询日志
    • mysqldumpslow
    • pt-query-digest

开启慢查询日志

在项目中我们会经常遇到慢查询,当我们遇到慢查询的时候一般都要开启慢查询日志,并且分析慢查询日志,找到慢sql,然后用explain来分析

系统变量

MySQL和慢查询相关的系统变量如下

参数 含义
slow_query_log 是否启用慢查询日志, ON为启用,OFF为没有启用,默认为OFF
log_output 日志输出位置,默认为FILE,即保存为文件,若设置为TABLE,则将日志记录到mysql.show_log表中,支持设置多种格式
slow_query_log_file 指定慢查询日志文件的路径和名字
long_query_time 执行时间超过该值才记录到慢查询日志,单位为秒,默认为10

执行如下语句看是否启用慢查询日志,ON为启用,OFF为没有启用

show variables like "%slow_query_log%"

可以看到我的没有启用,可以通过如下两种方式开启慢查询

修改配置文件

修改配置文件my.ini,在[mysqld]段落中加入如下参数

[mysqld]
log_output='FILE,TABLE'
slow_query_log='ON'
long_query_time=0.001

需要重启 MySQL 才可以生效,命令为 service mysqld restart

设置全局变量

我在命令行中执行如下2句打开慢查询日志,设置超时时间为0.001s,并且将日志记录到文件以及mysql.slow_log表中

set global slow_query_log = on;
set global log_output = 'FILE,TABLE';
set global long_query_time = 0.001;

想要永久生效得到配置文件中配置,否则数据库重启后,这些配置失效

分析慢查询日志

因为mysql慢查询日志相当于是一个流水账,并没有汇总统计的功能,所以我们需要用一些工具来分析一下

mysqldumpslow

mysql内置了mysqldumpslow这个工具来帮我们分析慢查询日志。

常见用法

# 取出使用最多的10条慢查询
mysqldumpslow -s c -t 10 /var/run/mysqld/mysqld-slow.log

# 取出查询时间最慢的3条慢查询
mysqldumpslow -s t -t 3 /var/run/mysqld/mysqld-slow.log 

# 得到按照时间排序的前10条里面含有左连接的查询语句
mysqldumpslow -s t -t 10 -g “left join” /database/mysql/slow-log

pt-query-digest

pt-query-digest是我用的最多的一个工具,功能非常强大,可以分析binlog、General log、slowlog,也可以通过show processlist或者通过tcpdump抓取的MySQL协议数据来进行分析。pt-query-digest是一个perl脚本,只需下载并赋权即可执行

下载和赋权

wget www.percona.com/get/pt-query-digest
chmod u+x pt-query-digest
ln -s /opt/soft/pt-query-digest /usr/bin/pt-query-digest

用法介绍

// 查看具体使用方法
pt-query-digest --help
// 使用格式
pt-query-digest [OPTIONS] [FILES] [DSN]

常用OPTIONS

  • --create-review-table  当使用--review参数把分析结果输出到表中时,如果没有表就自动创建。
  • --create-history-table  当使用--history参数把分析结果输出到表中时,如果没有表就自动创建。
  • --filter  对输入的慢查询按指定的字符串进行匹配过滤后再进行分析
  • --limit限制输出结果百分比或数量,默认值是20,即将最慢的20条语句输出,如果是50%则按总响应时间占比从大到小排序,输出到总和达到50%位置截止。
  • --host  mysql服务器地址
  • --user  mysql用户名
  • --password  mysql用户密码
  • --history 将分析结果保存到表中,分析结果比较详细,下次再使用--history时,如果存在相同的语句,且查询所在的时间区间和历史表中的不同,则会记录到数据表中,可以通过查询同一CHECKSUM来比较某类型查询的历史变化。
  • --review 将分析结果保存到表中,这个分析只是对查询条件进行参数化,一个类型的查询一条记录,比较简单。当下次使用--review时,如果存在相同的语句分析,就不会记录到数据表中。
  • --output 分析结果输出类型,值可以是report(标准分析报告)、slowlog(Mysql slow log)、json、json-anon,一般使用report,以便于阅读。
  • --since 从什么时间开始分析,值为字符串,可以是指定的某个”yyyy-mm-dd [hh:mm:ss]”格式的时间点,也可以是简单的一个时间值:s(秒)、h(小时)、m(分钟)、d(天),如12h就表示从12小时前开始统计。
  • --until 截止时间,配合—since可以分析一段时间内的慢查询。

常用DSN

A    指定字符集
D    指定连接的数据库
P    连接数据库端口
S    连接Socket file
h    连接数据库主机名
p    连接数据库的密码
t    使用--review或--history时把数据存储到哪张表里
u    连接数据库用户名

DSN使用key=value的形式配置;多个DSN使用,分隔

使用示例

# 展示slow.log中最慢的查询的报表
pt-query-digest slow.log

# 分析最近12小时内的查询
pt-query-digest --since=12h slow.log

# 分析指定范围内的查询
pt-query-digest slow.log --since '2020-06-20 00:00:00' --until '2020-06-25 00:00:00'

# 把slow.log中查询保存到query_history表
pt-query-digest --user=root --password=root123 --review h=localhost,D=test,t=query_history --create-review-table slow.log

# 连上localhost,并读取processlist,输出到slowlog
pt-query-digest --processlist h=localhost --user=root --password=root123 --interval=0.01 --output slowlog

# 利用tcpdump获取MySQL协议数据,然后产生最慢查询的报表
# tcpdump使用说明:https://blog.csdn.net/chinaltx/article/details/87469933
tcpdump -s 65535 -x -nn -q -tttt -i any -c 1000 port 3306 > mysql.tcp.txt
pt-query-digest --type tcpdump mysql.tcp.txt

# 分析binlog
mysqlbinlog mysql-bin.000093 > mysql-bin000093.sql
pt-query-digest  --type=binlog mysql-bin000093.sql

# 分析general log
pt-query-digest  --type=genlog  localhost.log

用法实战

编写存储过程批量造数据

在实际工作中没有测试性能,我们经常需要改造大批量的数据,手动插入是不太可能的,这时候就得用到存储过程了

CREATE TABLE `kf_user_info` (
  `id` int(11) NOT NULL COMMENT '用户id',
  `gid` int(11) NOT NULL COMMENT '客服组id',
  `name` varchar(25) NOT NULL COMMENT '客服名字'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户信息表';

如何定义一个存储过程呢?

CREATE PROCEDURE 存储过程名称 ([参数列表])
BEGIN
    需要执行的语句
END

举个例子,插入id为1-100000的100000条数据

用Navicat执行

-- 删除之前定义的
DROP PROCEDURE IF EXISTS create_kf;

-- 开始定义
CREATE PROCEDURE create_kf(IN loop_times INT)
BEGIN
	DECLARE var INT;
	SET var = 1;
	WHILE var < loop_times DO
		INSERT INTO kf_user_info (`id`,`gid`,`name`)
		VALUES (var, 1000, var);
		SET var = var + 1;
	END WHILE;
END;

-- 调用
call create_kf(100000);

存储过程的三种参数类型

参数类型 是否返回 作用
IN 向存储过程传入参数,存储过程中修改该参数的值,不能被返回
OUT 把存储过程计算的结果放到该参数中,调用者可以得到返回值
INOUT IN和OUT的结合,即用于存储过程的传入参数,同时又可以把计算结构放到参数中,调用者可以得到返回值

用MySQL执行

得用DELIMITER 定义新的结束符,因为默认情况下SQL采用(;)作为结束符,这样当存储过程中的每一句SQL结束之后,采用(;)作为结束符,就相当于告诉MySQL可以执行这一句了。但是存储过程是一个整体,我们不希望SQL逐条执行,而是采用存储过程整段执行的方式,因此我们就需要定义新的DELIMITER ,新的结束符可以用(//)或者($$)

因为上面的代码应该就改为如下这种方式

DELIMITER //
CREATE PROCEDURE create_kf_kfGroup(IN loop_times INT)
BEGIN
	DECLARE var INT;
	SET var = 1;
	WHILE var <= loop_times DO
		INSERT INTO kf_user_info (`id`,`gid`,`name`)
		VALUES (var, 1000, var);
		SET var = var + 1;
	END WHILE;
END //
DELIMITER ;

查询已经定义的存储过程

show procedure status;

开始执行慢sql

select * from kf_user_info where id = 9999;
select * from kf_user_info where id = 99999;
update kf_user_info set gid = 2000 where id = 8888;
update kf_user_info set gid = 2000 where id = 88888;

可以执行如下sql查看慢sql的相关信息。

SELECT * FROM mysql.slow_log order by start_time desc;

查看一下慢日志存储位置

show variables like "slow_query_log_file"
pt-query-digest /var/lib/mysql/VM-0-14-centos-slow.log

执行后的文件如下

# Profile
# Rank Query ID                            Response time Calls R/Call V/M
# ==== =================================== ============= ===== ====== ====
#    1 0xE2566F6154AFF41948FE497E53631B43   0.1480 56.1%     4 0.0370  0.00 UPDATE kf_user_info
#    2 0x2DFBC6DBF0D68EF2EC2AE954DC37A1A4   0.1109 42.1%     4 0.0277  0.00 SELECT kf_user_info
# MISC 0xMISC                               0.0047  1.8%     2 0.0024   0.0 <2 ITEMS>

从最上面的统计sql中就可以看到执行慢的sql

可以看到响应时间,执行次数,每次执行耗时(单位秒),执行的sql

下面就是各个慢sql的详细分析,比如,执行时间,获取锁的时间,执行时间分布,所在的表等信息

不由得感叹一声,真是神器,查看慢sql超级方便

最后说一个我遇到的一个有意思的问题,有一段时间线上的接口特别慢,但是我查日志发现sql执行的很快,难道是网络的问题?

为了确定是否是网络的问题,我就用拦截器看了一下接口的执行时间,发现耗时很长,考虑到方法加了事务,难道是事务提交很慢?

于是我用pt-query-digest统计了一下1分钟左右的慢日志,发现事务提交的次很多,但是每次提交事务的平均时长是1.4s左右,果然是事务提交很慢。

参考博客

很全的一篇文章
[0]https://zhuanlan.zhihu.com/p/106405711
[1]https://blog.csdn.net/lt326030434/article/details/109222848
[1]https://tech.meituan.com/2014/06/30/mysql-index.html
[2]https://blog.csdn.net/itguangit/article/details/82145322
[3]https://mp.weixin.qq.com/s/_SWewX-8nFam20Wcg6No1Q
下载
[4]https://www.cnblogs.com/zi-xing/p/4269854.html

到此这篇关于MySQL如何快速定位慢SQL的实战 的文章就介绍到这了,更多相关MySQL 定位慢SQL内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • MySQL慢查询的坑

    一条慢查询会造成什么后果?年轻时,我一直觉得不就是返回数据会慢一些么,用户体验变差?其实远远不止,我经历过几次线上事故,有一次就是由一条SQL慢查询导致的. 记得那是一条查询SQL,数据量万级时还保持在0.2秒内,随着某一段时间数据猛增,耗时一度达到了2-3秒!没有命中索引,导致全表扫描.explain 中extra显示:Using where; Using temporary; Using filesort,被迫使用了临时表排序,由于是高频查询,并发一起来很快就把DB线程池打满了,导致大量查询

  • MySQL 查询速度慢的原因

    谈到MySQL性能优化,查询优化作为优化的源头,它也是最能体现一个系统是否更快.本章以及接下来的几章将会着重讲解关于查询性能优化的内容,从中会介绍一些查询优化的技巧,帮助大家更深刻地理解MySQL如何真正地执行查询.究竟慢在哪里.如何让其快起来,并明白高效和低效的原因何在,这样更有助于你更好的来优化查询SQL语句. 本章从"为什么查询速度这么慢"开始谈起,让你能够清楚的知道查询可能会慢在哪些环节,这样将有助于你更好的优化查询,做到心中有数,高人一筹. 一.慢在哪? **真正衡量查询速度

  • MySQL 慢查询日志深入理解

    什么是慢查询日志 MySQL的慢查询日志是 MySQL提供的一种日志记录,它用来记录在 MySQL 中响应时间超过阀值的语句,具体指运行时间超过long_query_time 值的 SQL,则会被记录到慢查询日志中 具体指运行时间超过 long_query_time 值的 SQL,则会被记录到慢查询日志中.long_query_time 的默认值为 10, 意思是运行 10 秒以上的语句 由它来查看哪些 SQL 超出了我们的最大忍耐时间值,比如一条SQL执行超过 5 秒钟,我们就算慢 SQL,希

  • MySQL 慢日志相关知识总结

    1.慢日志简介 慢日志全称为慢查询日志(Slow Query Log),主要用来记录在 MySQL 中执行时间超过指定时间的 SQL 语句.通过慢查询日志,可以查找出哪些语句的执行效率低,以便进行优化. 默认情况下,MySQL 并没有开启慢日志,可以通过修改 slow_query_log 参数来打开慢日志.与慢日志相关的参数介绍如下: slow_query_log:是否启用慢查询日志,默认为0,可设置为0.1,1表示开启. slow_query_log_file:指定慢查询日志位置及名称,默认值

  • MySQL慢查询优化解决问题

    目录 1. MySQL慢查询介绍 2.发现问题(主动/被动) 3.找到原因-对症下药 1.  MySQL慢查询介绍 MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中.long_query_time的默认值为10,意思是运行10S以上的语句.默认情况下,Mysql数据库并不启动慢查询日志,需要我们手动来设置这个参数,当然,如果不是调优需要的话,一般不建议启动该参

  • MySQL定位并优化慢查询sql的详细实例

    目录 1.如何定位并优化慢查询sql a.根据慢日志定位慢查询sql b.使用explain等工具分析sql c.修改sql或者尽量让sql走索引 2.联合索引的最左匹配原则的成因 简单说下什么是最左匹配原则 最左匹配原则的原理 3.索引是建立得越多越好吗 总结 1.如何定位并优化慢查询sql a.根据慢日志定位慢查询sql SHOW VARIABLES LIKE '%query%' 查询慢日志相关信息 slow_query_log 默认是off关闭的,使用时,需要改为on 打开 slow_qu

  • docker mysql容器如何开启慢查询日志

    目录 1.进入容器 登陆账号 2.查看慢日志相关信息 1.进入容器 登陆账号 docker 查看 运行的容器 docker ps 进入容器: docker exec -it dc8880c13fef /bin/bash 输入用户名密码登陆mysql mysql -u root -p 然后输入密码登陆进去 2.查看慢日志相关信息 默认慢日志是关闭的.show variables like ‘slow%’;(或者使用,看别的博主说会有版本的区别,那就使用双百分号:show variables lik

  • MySQL优化方案之开启慢查询日志

    目录 前言 设置慢查询日志 测试 附:日志分析工具mysqldumpslow 总结 前言 本方案只适应于小的项目.项目未上线或者紧急情况下可采用这种方式,一旦开启慢日志查询会增加数据库的压力,所以一般采用后台对数据操作时间写入日志文件中,每一周定时进行清除日志 mysql优化方案:开启慢查询日志(查询sql执行超过一秒以上sql等等) 开启慢查询日志:可以让MySQL记录下查询超过指定时间的语句,通过定位分析性能的瓶颈,才能更好的优化数据库系统的性能. 参数说明: slow_query_log

  • MySQL如何快速定位慢SQL的实战

    目录 开启慢查询日志 系统变量 修改配置文件 设置全局变量 分析慢查询日志 mysqldumpslow pt-query-digest 开启慢查询日志 在项目中我们会经常遇到慢查询,当我们遇到慢查询的时候一般都要开启慢查询日志,并且分析慢查询日志,找到慢sql,然后用explain来分析 系统变量 MySQL和慢查询相关的系统变量如下 参数 含义 slow_query_log 是否启用慢查询日志, ON为启用,OFF为没有启用,默认为OFF log_output 日志输出位置,默认为FILE,即

  • MySQL实战记录之如何快速定位慢SQL

    目录 开启慢查询日志 系统变量 修改配置文件 设置全局变量 分析慢查询日志 mysqldumpslow pt-query-digest 用法实战 总结 开启慢查询日志 在项目中我们会经常遇到慢查询,当我们遇到慢查询的时候一般都要开启慢查询日志,并且分析慢查询日志,找到慢sql,然后用explain来分析 系统变量 MySQL和慢查询相关的系统变量如下 参数 含义 slow_query_log 是否启用慢查询日志, ON为启用,OFF为没有启用,默认为OFF log_output 日志输出位置,默

  • mysql命令行下执行sql文件的几种方法

    目录 第一种方法:未连接mysql数据库时 第二方法:在已经连接数据库的情况下,此时命令提示符为mysql>, 用MySQL的source命令导入SQL文件实战记录 达到目的:通过命令行的方式,将tsinfo180516.sql文件导入到数据库demo1中. 效果图 第一种方法:未连接mysql数据库时 在mysql命令行下执行sql文件 运行--cmd C:\Users\lenovo>mysql -u账号 -p密码 -D数据库名 < sql文件绝对路径 C:\Users\lenovo&

  • Mysql效率优化定位较低sql的两种方式

    关于mysql效率优化一般通过以下两种方式定位执行效率较低的sql语句. 通过慢查询日志定位那些执行效率较低的 SQL 语句,用 --log-slow-queries[=file_name] 选项启动时, mysqld 会 写一个包含所有执行时间超过 long_query_time 秒的 SQL 语句的日志文件,通过查看这个日志文件定位效率较低的 SQL . 慢查询日志在查询结束以后才纪录,所以在应用反映执行效率出现问题的时候查询慢查询日志并不能定位问题,可以使用 show processlis

  • MySQL性能瓶颈排查定位实例详解

    本文实例讲述了MySQL性能瓶颈排查定位的方法.分享给大家供大家参考,具体如下: 导读 从一个现场说起,全程解析如何定位性能瓶颈. 排查过程 收到线上某业务后端的MySQL实例负载比较高的告警信息,于是登入服务器检查确认. 1. 首先我们进行OS层面的检查确认 登入服务器后,我们的目的是首先要确认当前到底是哪些进程引起的负载高,以及这些进程卡在什么地方,瓶颈是什么. 通常来说,服务器上最容易成为瓶颈的是磁盘I/O子系统,因为它的读写速度通常是最慢的.即便是现在的PCIe SSD,其随机I/O读写

  • MySQL实现快速删除所有表而不删除数据库的方法

    本文实例讲述了MySQL实现快速删除所有表而不删除数据库的方法.分享给大家供大家参考,具体如下: 如果直接使用phpmyadmin操作的话肯定非常简单,勾选数据表->点击删除->点击确定,操作完毕! 这里介绍一下快速删除数据表的SQL命令操作方法. 删除表的命令: drop table 表名; 如果有200张表,执行200次,想想就不想动手了. 下面提供一个使用information_schema库的方案: 复制代码 代码如下: SELECT CONCAT('drop table ',tabl

  • 查找MySQL中查询慢的SQL语句方法

    如何在mysql查找效率慢的SQL语句呢?这可能是困然很多人的一个问题,MySQL通过慢查询日志定位那些执行效率较低的SQL 语句,用--log-slow-queries[=file_name]选项启动时,mysqld 会写一个包含所有执行时间超过long_query_time 秒的SQL语句的日志文件,通过查看这个日志文件定位效率较低的SQL .下面介绍MySQL中如何查询慢的SQL语句 一.MySQL数据库有几个配置选项可以帮助我们及时捕获低效SQL语句 1,slow_query_log 这

  • MySQL如何快速导入数据

    前言: 日常学习和工作中,经常会遇到导数据的需求.比如数据迁移.数据恢复.新建从库等,这些操作可能都会涉及大量数据的导入.有时候导入进度慢,电脑风扇狂转真的很让人崩溃,其实有些小技巧是可以让导入更快速的,本篇文章笔者会谈一谈如何快速的导入数据. 注:本篇文章只讨论如何快速导入由逻辑备份产生的SQL脚本,其他文件形式暂不讨论. 1.尽量减小导入文件大小 首先给个建议,导出导入数据尽量使用MySQL自带的命令行工具,不要使用Navicat.workbench等图形化工具.特别是大数据量的时候,用My

  • MySQL基础快速入门知识总结(附思维导图)

    目录 前言 一.数据库基础知识 1.什么是数据库 2.数据库的分类 3.数据库的常用语言 4.数据库的常用操作方式 5.MySQL的架构 二.数据库的增删改查 1.创建数据库 2.查询数据库 3.修改数据库 4.删除数据库 三.表的增删改查 1.创建表 2.查询表 3.修改表 4.删除表 四.记录的增删改查 1.插入记录 2.查询记录(最常用) 3.修改记录 4.删除记录 五.字段类型 1.数字型 1.1整数型 1.2小数型 2.文本型 3.日期时间 六.字段属性 总结 前言 本文是我这段时间自

  • MySQL如何快速创建800w条测试数据表

    目录 一.数据插入思路 1.创建内存表 2.创建普通表 3.创建存储函数 4.创建存储过程 6.导入数据 7.内存不足 8.查看结果 9.插入800W条数据 二.MySQL深度分页 1.测试深度分页 一.数据插入思路 如果一条一条插入普通表的话,效率太低下,但内存表插入速度是很快的,可以先建立一张内存表,插入数据后,在导入到普通表中. 1.创建内存表  View Code 2.创建普通表 普通表参数设置和内存表相同,否则从内存表往普通标导入数据会报错.  View Code 3.创建存储函数 产

随机推荐