mysql的慢查询分析与性能调优工具使用

1次阅读

需先配置 slow_query_log_file 绝对路径并确保 MySQL 进程有写权限,再用 SHOW VARIABLES 确认启用状态、路径和阈值;动态开启用 SET GLOBAL,永久生效需写入 my.cnf。

mysql 的慢查询分析与性能调优工具使用

如何开启并确认 MySQL 慢查询日志是否生效

慢查询分析的前提是日志得真正写进去。很多人配置了 slow_query_log = ONlong_query_time = 2,但查不到日志,根本原因是没指定 slow_query_log_file 路径,或者 MySQL 进程对目标目录无写权限。

实操建议:

  • SHOW VARIABLES LIKE 'slow_query_log%'; 确认三项关键变量:是否启用、日志路径、阈值
  • 路径必须是 MySQL 进程用户(如 mysql)可写的绝对路径,例如 /var/log/mysql/mysql-slow.log,不能是相对路径或家目录
  • long_query_time 默认是 10 秒,生产环境建议设为 1.00.5;注意它只对执行时间 ≥ 阈值的语句生效,不包含锁等待时间(除非开启 log_queries_not_using_indexes
  • 动态开启需执行 SET GLOBAL slow_query_log = ON;,但重启后失效;永久生效要写进 my.cnf[mysqld]

mysqldumpslow 快速定位高频 / 高耗时 SQL

mysqldumpslow 是 MySQL 自带的轻量级分析 工具,适合快速筛出“最慢的 10 条”或“出现最多的 5 条”,比直接 grep 日志高效得多。

常见组合用法:

  • mysqldumpslow -s t -t 10 /var/log/mysql/mysql-slow.log:按总执行时间排序,取前 10 条
  • mysqldumpslow -s c -t 5 /var/log/mysql/mysql-slow.log:按出现次数排序,看哪些 SQL 被反复执行
  • mysqldumpslow -g "SELECT.*FROM orders" /var/log/mysql/mysql-slow.log:过滤含特定模式的慢查询(注意正则语法简单,不支持复杂匹配)

注意:mysqldumpslow 会自动归一化 SQL(比如把 WHERE id = 123 变成 WHERE id = N),所以统计的是“模板维度”的频次,不是原始语句条数。

pt-query-digest:精准分析 + 索引建议的核心工具

Percona Toolkit 的 pt-query-digest 是业界事实标准,它能解析慢日志、聚合统计、识别全表扫描、估算索引收益,还能输出可读报告和优化建议。

典型使用流程:

  • 基础分析:
    pt-query-digest /var/log/mysql/mysql-slow.log
  • 只看最耗时的 3 条 SQL 及其执行计划:
    pt-query-digest --limit 3 /var/log/mysql/mysql-slow.log
  • 结合 EXPLAIN 分析某类慢查询:
    pt-query-digest --explain h=127.0.0.1,u=root,p=xxx /var/log/mysql/mysql-slow.log

    (需确保账号有 PROCESS 权限)

  • 输出 HTML 报告便于分享:
    pt-query-digest --report-format html /var/log/mysql/mysql-slow.log > slow-report.html

关键点:它默认只分析 Query 类型语句,若日志里有 ConnectQuit 等非查询事件,需加 --filter '$event->{fingerprint} =~ m/^select|^update|^insert|^delete/' 过滤。

为什么 explain 显示 type=ALL 却没走索引

这是调优中最常被误判的点——EXPLAIN 输出 type = ALL 表示全表扫描,但未必是“没建索引”,更可能是索引失效或优化器误选。

排查优先级:

  • 检查 WHERE 条件字段是否在索引最左列,比如索引是 (a,b,c),但查询写了 WHERE b = 1,就无法使用该索引
  • 确认字段类型是否 隐式转换:比如 user_idINT,但 SQL 写成 WHERE user_id = '123',会导致索引失效
  • 查看 key_len 是否符合预期,若远小于索引定义长度,说明只用了部分列
  • ANALYZE TABLE table_name; 更新统计信息,避免优化器因过期数据误判
  • 必要时强制指定索引:SELECT * FROM t USE INDEX (idx_a_b) WHERE a = 1 AND b = 2;,再对比执行时间

真正难调的,往往不是缺索引,而是复合条件下的索引覆盖、排序字段顺序、以及 ORDER BY + LIMIT 场景下优化器放弃索引选择文件排序。

text=ZqhQzanResources