背景:
做为一个MySQL DBA,分析慢查询是日常主要的工作之一,之前一直使用mysqlsla作为分析慢查询的, 因为简单并且也能满足自己对慢查询分析的要求,对于另一个工具pt-query-digest并不熟悉,对于pt系列的工具之前也介绍过一些,Percona Toolkit确实厉害,整个全家桶:包含了备份、监控、各种分析工具,以及定制化过的MySQL Server。 现在本文来介绍下如何使用pt-query-digest,也方便自己查阅。
很多人都把pt-query-digest作为分析mysql工具的首选,因为它可以从logs、processlist、和tcpdump 来分析MySQL的状况,logs包括slow log、general log、binlog。也可以把分析结果输出到文件中,或则把文件写到表中。分析过程是先对查询语句的条件进行参数化,然后对参数化以后的查询进行分组统计,统计出各查询的执行时间、次数、占比等,可以借助分析结果找出问题进行优化。
使用方法:
下载:
进入到下载页,下载Percona Toolkit
依赖包:
Centos:
yum -y install perl-TermReadKey perl-Time-HiRes perl-IO-Socket-SSL.noarch
使用方法:
pt-query-digest [OPTIONS] [FILES] [DSN]
说明:
pt-query-digest分析slow log、general log和binary log,还可以分析来自SHOW PROCESSLIST的查询和来自tcpdump的MySQL协议数据。 默认情况下,查询按fingerprint分组,并按查询时间的降序排列(最慢的查询排在第一位)。 如果未提供文件,则该工具读取STDIN。 可选的DSN用于某些选项,例如--since和--until。
示例:
1)从slow.log报告最慢的查询
pt-query-digest slow.log
2)从host1上的processlist里报告最慢的查询
pt-query-digest --processlist h=host1
3)使用tcppdump捕获MySQL协议数据,然后报告最慢的查询
tcpdump -s 65535 -x -nn -q -tttt -i any -c 1000 port 3306 > mysql.tcp.txt pt-query-digest --type tcpdump mysql.tcp.txt
4)将查询数据从slow.log保存到host2,以供以后查看和趋势分析
pt-query-digest --review h=host2 --no-report slow.log
描述
pt-query-digest是一种复杂但易于使用的工具,用于分析MySQL查询。它可以分析来自MySQL慢速日志,常规日志和二进制日志的查询(二进制日志必须首先转换为文本,请参阅--type)。默认情况下,该工具报告哪些查询最慢。可以使用--group-by、--filter和--embedded-attributes之类的选项来创建更复杂和定制的报告。
pt-query-digest具有两个功能:查询查看(--review)和查询历史记录(--history)。使用--review选项时,所有查询都将保存到数据库中。当再次使用--review运行该工具时,数据库中标记为已审阅的查询不会打印在报告中,只显示需要审查的新查询。使用--history选项时,每个查询的指标(查询时间,锁时间等)都保存到数据库中。每次使用--history运行该工具时,都会保存更多的历史数据,这些数据可用于随时间推移趋势和分析查询性能。
属性
如果使用--filter,-ignore-attributes和其他与属性相关的选项时,必须熟悉这些属性,如果不需要自定义可以跳过属性说明。
pt-query-digest处理event,这些event是称为属性的键值对的集合,能识别出大多数属性:Query_time,Lock_time等。如果编写--filter,请务必在使用每个event之前检查其属性是否已定义,否则过滤器代码可能会因“使用未初始化的值”错误而使工具崩溃。有关常见和--type特定属性的列表:为任何输入转储event属性:
$ pt-query-digest \ slow.log \ --filter 'print Dumper $event' \ --no-report \ --sample 1
产生很多带有“ attribute => value”对的输出:
$VAR1 = { Query_time => '0.033384', Rows_examined => '0', Rows_sent => '0', Thread_id => '10', Tmp_table => 'No', Tmp_table_on_disk => 'No', arg => 'SELECT col FROM tbl WHERE id=5', bytes => 103, cmd => 'Query', db => 'db1', fingerprint => 'select col from tbl where id=?', host => '', pos_in_log => 1334, ts => '071218 11:48:27', user => '[SQL_SLAVE]' };
通过编写--filter,可以创建从现有属性派生的新属性。 例如,要创建一个名为Row_ratio的属性以检查Rows_sent与Rows_examined的比率,请指定一个过滤器:
--filter '($event->{Row_ratio} = $event->{Rows_sent} / ($event->{Rows_examined})) && 1'
需要使用&& 1技巧来创建始终为true的有效单行语法,新属性将自动出现在输出中:
# Row ratio 1.00 0.00 1 0.50 1 0.71 0.50
输出值
默认的--output是查询分析报告。 --no-report选项控制是否打印此报告。使用--review或--history时,解析所有查询但不显示报告。
报告里的列说明:
Column Meaning ============ ========================================================== Rank 查询在分析的整个查询集中的排名 Query ID 查询的指纹(fingerprint) Response time 总响应时间,占总响应时间的百分比 Calls 执行此查询的次数 R/Call 每次执行的平均响应时间 V/M 响应时间的方差均值比,变异数对平均数比,可说明样本的分散程度. 这个值大,往往是值得考虑优化的对象. Item 查询的简单显示,包含了查询涉及的表对象。 示例: # Rank Query ID Response time Calls R/Call V/M # ==== ================================== ============= ===== ====== ===== # 1 0x95BE8AA82ED172A4ABAFC4ED3B792467 6.0100 100.0% 2 3.0050 0.00 SELECT x
拆分多部分说明报告信息:
# Query 2: 0.01 QPS, 0.02x conc, ID 0xFDEA8D2993C9CAF30x6F7A87D11DDD9CC608CCACD1427CD832 at byte 160665
说明:查询的顺序号、每秒查询量、查询的近似并发度(根据时间隔和总Query_time计算)、查询ID。如果使用--review,则此ID是数据库中查询校验和的十六进制。可以使用SELECT ...之类的查询从数据库中选择已审核查询的详细信息:WHERE checksum = 0xFDEA8D2993C9CAF3。160665表示在文本中的偏移量,可以利用偏移量到慢查询日志里定位具体的sql语句,定位方法如下:
tail -c +160665 /path/to/slow.log. | head
如果想打印出特定查询的每个样本:去掉查询ID的0x
pt-query-digest test2-slow.log --no-report --output slowlog --filter '$event->{fingerprint} && make_checksum($event->{fingerprint}) eq "6F7A87D11DDD9CC608CCACD1427CD832"' # Time: 2020-02-28T10:49:34 # User@Host: root[root] @ test2 [] # Thread_id: 19 # Query_time: 3.003152 Lock_time: 0.002218 Rows_sent: 1 Rows_examined: 2 use orchestrator; select count(*),sleep(3) from cluster_domain_name;
接下来是有关此类查询的指标表:
# Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 20 1 # Exec time 13 3s 3s 3s 3s 3s 0 3s # Lock time 33 2ms 2ms 2ms 2ms 2ms 0 2ms # Rows sent 5 1 1 1 1 1 0 1 # Rows examine 11 2 2 2 2 2 0 2 # Query size 25 49 49 49 49 49 0 49 # Row ratio 11 0.50 0.50 0.50 0.50 0.50 0 0.50
第一行是表的列标题:属性、百分比(总计的百分比),总计、最大、最小、平均、95%的值小于或等于此值、标准偏差和中位数都是从第95个百分位数计算得出的。
接下来,将查询有关用户,数据库和时间范围的统计信息:
# Users 1 user1 # Databases 2 db1(1), db2(1) # Time range 2008-11-26 04:55:18 to 2008-11-27 00:15:15
用户和数据库显示为不同值的计数。如果只有一个,则会单独显示; 如果有很多,将显示每个最常出现的频率,然后显示它出现的次数。
然后看执行时间分布:
# Query_time distribution # 1us # 10us # 100us # 1ms # 10ms ##### # 100ms #################### # 1s ########## # 10s+
执行时间显示时间聚类的分布图。 每个查询都进入“存储桶”之一,并被计算在内。 第一个存储桶的所有值都在“单个微秒范围”内-小于10us。 第二个是“数十微秒”,从10us到(但不包括)100us; 等等。 可以通过指定--report-histogram更改图表属性,但仅限于基于时间的属性。
然后看表信息:
# Tables # SHOW TABLE STATUS LIKE 'table1'\G # SHOW CREATE TABLE `table1`\G # EXPLAIN SELECT * FROM table1\G
通过给出的信息可以得到表的基本信息,以及其执行计划,对于无法执行的非SELECT查询,该工具会尝试将该查询转换为大致等效的SELECT查询,并将其添加到下面。
QUERY REVIEW
--review是存储所有已分析的查询,可以将元数据添加到查询类别中,例如将其标记为后续跟踪,为查询添加注释或为问题跟踪系统使用问题ID标记它们。可以存储历史数据,例如行数,查询时间以及通常可以在报告中看到的任何内容。
要使用此功能,请使用--review选项运行pt-query-digest。它将指纹和其他信息存储到指定的表中。下次使用相同的选项运行它时,它将执行以下操作:
- 不会显示已审核的查询。如果为review_by列设置了值,则认为该查询已被审核。 (如果想查看已经查看过的查询,请使用--report-all选项。)
- 已查看但未出现在输出中的查询将导致每个段落第一行中查询编号序列的空白。--limit指定的值仍然会被接受。因此,如果看了前10名中的所有查询并要求输入前10名,则输出中将看不到任何内容。
-
如果想查看已经查看过的查询,可以指定--report-all。然后,将看到正常的分析输出,但还将看到执行时间图下方的审阅表中的信息。例如:
# Review information # comments: really bad IN() subquery, fix soon! # first_seen: 2008-12-01 11:48:57 # jira_ticket: 1933 # last_seen: 2008-12-18 11:49:07 # priority: high # reviewed_by: xaprb # reviewed_on: 2008-12-18 15:03:11
此元数据很有用,因为当分析查询时,会将注释直接集成到报告中。
FINGERPRINTS
简而言之就是将将相似的查询分组在一起,如:
SELECT name, password FROM user WHERE id='12823'; select name, password from user where id=5;
可以合并当成:
select name, password from user where id=?
参数说明: pt-query-digest --help
--ask-pass FALSE #连接到MySQL时提示输入密码 --attribute-aliases db|Schema #属性列表|别名等(默认db | Schema) --attribute-value-limit 0 #属性值的限制(默认为0) --charset (No value) #默认字符集 #逗号分隔的配置文件列表;如果指定,则必须是命令行上的第一个选项 --config /etc/percona-toolkit/percona-toolkit.conf,/etc/percona-toolkit/pt-query-digest.conf,/root/.percona-toolkit.conf,/root/.pt-query-digest.conf --continue-on-error TRUE #即使有错误也继续解析(默认为是) --create-history-table TRUE #创建--history表(如果不存在)(默认为yes) --create-review-table TRUE #创建--review表(如果不存在)(默认为yes) --daemonize FALSE #Fork到后台并从shell分离 --database (No value) #连接到该数据库 --defaults-file (No value) #仅从给定文件读取mysql选项 --embedded-attributes (No value) #两个Perl正则表达式模式,用于捕获查询中嵌入的伪属性 --expected-range 5,10 #当数量多于或少于预期时解释项目(默认值为5,10) --explain (No value) #使用此DSN对示例查询运行EXPLAIN并打印结果 --filter (No value) #丢弃此Perl代码未返回true的事件 --group-by fingerprint #要对事件的哪个属性进行分组(默认fingerprint) --help TRUE #显示帮助并退出 --history (No value) #在给定表中保存每个查询类的指标。 pt-query-digest将查询指标(查询时间,锁定时间等)保存到此表中,以便您查看查询类如何随时间变化 --host (No value) #连接到主机 --ignore-attributes arg,cmd,insert_id,ip,port,Thread_id,timestamp,exptime,flags,key,res,val,server_id,offset,end_log_pos,Xid #不要聚合这些属性 --inherit-attributes db,ts #如果丢失,则从具有属性的最后一个事件继承这些属性(默认db,ts) --interval .1 #轮询show processlist的频率,以秒为单位(默认为.1) --iterations 1 #在收集和报告周期中迭代多少次(默认为1) --limit 95%:20 #将输出限制为给定的百分比或计数(默认为95%:20) --log (No value) #守护进程时将所有输出打印到此文件 --max-hostname-length 10 #将报告中的主机名修剪到此长度。 0 =不修剪主机名(默认为10) --max-line-length 74 #将行修剪到此长度。 0 =不修剪线条(默认74) --order-by Query_time:sum #按此属性:聚合函数对事件进行排序(默认Query_time:sum) --outliers Query_time:1:10 #按属性:百分比:计数报告异常值(默认查询时间:1:10) --output report #如何格式化和打印查询分析结果(默认report) --password (No value) #连接时使用的密码 --pid (No value) #创建给定的PID文件 --port (No value) #用于连接的端口号 --preserve-embedded-numbers FALSE #查询时保留数据库/表名中的数字 --processlist (No value) #使用--interval sleep轮询此DSN的进程列表以进行查询 --progress time,30 #将进度报告打印到STDERR(默认时间30) --read-timeout 0 #等待的超时时间,等待来自输入的事件; 0表示永远等待(默认值为0)。 可选后缀s =秒,m =分钟,h =小时,d =天; 如果没有后缀,则使用s。 --report TRUE #打印每个--group-by属性的查询分析报告(默认为yes) --report-all FALSE #报告所有查询,甚至包括已审核的查询 --report-format rusage,date,hostname,files,header,profile,query_report,prepared #打印查询分析报告的这些部分 --report-histogram Query_time #绘制此属性值的分布图(默认Query_time) --resume (No value) #如果指定,该工具会将最后一个文件偏移(如果有的话)写入给定的文件名 --review (No value) #保存查询以供以后查看,并且不报告已查看的 --run-time (No value) #每个迭代要运行多长时间。可选后缀s =秒,m =分钟,h =小时,d =天;如果没有后缀,则使用s。 --run-time-mode clock #设置--run-time的值所用的值(默认clock) --sample (No value) #过滤掉每个查询中除前N个事件外的所有事件 --set-vars #在此以逗号分隔的(变量=值对)列表中设置MySQL变量 --show-all #显示这些属性的所有值 --since (No value) #解析仅查询比该值新的查询(自此日期以来解析查询) --slave-password (No value) #设置用于连接到从的密码 --slave-user (No value) #设置用于连接到从的用户 --socket (No value) #用于连接的套接字文件 --timeline FALSE #显示事件的时间表 --type slowlog #要解析的输入的类型(默认慢日志) --until (No value) #仅解析早于此值的查询(直到此日期为止解析查询) --user (No value) #用于登录的用户(如果不是当前用户) --variations #报告这些属性值的变化数量 --version FALSE #显示版本并退出 --version-check TRUE #检查最新版本的Percona Toolkit,MySQL和其他程序(默认为是) --vertical-format TRUE #在报告的SQL查询中输出尾随的“ \ G”(默认为是) --watch-server (No value) #此选项告诉pt-query-digest在解析tcpdump时要监视哪个服务器IP地址和端口(例如“ 10.0.0.1:3306”)(对于--type tcpdump);其他所有服务器均被忽略