MySQL慢查询日志开启与参数分析:用mysqldumpslow定位拖慢网站的SQL

    发布时间:2026-09-10 05:04 更新时间:2026-09-10 05:04 阅读量:0

    网站访问变慢,很多时候问题不在PHP或Nginx,而在数据库。尤其当WordPress、ThinkPHP这类程序执行了大量低效SQL,MySQL每次都要全表扫描或排序,请求一多,数据库连接数被占满,整个站点就卡住了。要快速定位拖慢网站的SQL,最直接的办法就是开启MySQL慢查询日志,再用自带的mysqldumpslow工具做汇总分析。这篇文章面向实际运维场景,介绍如何开启日志、调整参数,以及从分析结果中找出真正需要优化的语句。

    慢查询日志是什么,开启前先了解这些参数

    慢查询日志记录的是执行时间超过指定阈值的SQL语句。MySQL通过几个系统变量控制日志行为,常见的有slow_query_log(是否开启)、slow_query_log_file(日志文件路径)、long_query_time(阈值秒数,默认10秒),还有log_queries_not_using_indexes(记录未走索引的查询)和min_examined_row_limit(仅记录扫描行数超过该值的语句)。注意,MySQL 5.1.29以后long_query_time最小可设为0,单位是秒,支持小数,比如0.5表示500毫秒。对大多数网站来说,超过1秒的SELECT就值得关注,建议先设为2秒,再根据负载逐步调低。

    查看当前状态可以用如下命令:

    mysql> SHOW VARIABLES LIKE 'slow_query%';
    mysql> SHOW VARIABLES LIKE 'long_query_time';
    mysql> SHOW VARIABLES LIKE 'log_queries_not_using_indexes';

    如果日志没开启,直接执行SET GLOBAL命令就能临时打开,但MySQL重启后会丢失。建议直接写进配置文件,例如/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf(具体路径以你的发行版和安装方式为准):

    [mysqld]
    slow_query_log = 1
    slow_query_log_file = /var/log/mysql/mysql-slow.log
    long_query_time = 2
    log_queries_not_using_indexes = 1

    配置后重启MySQL服务生效。另外要注意,log_queries_not_using_indexes开启后,即使查询很快,只要没走索引也会被记下来,日志量可能明显增大,生产环境需根据磁盘空间权衡。还可以配合log_throttle_queries_not_using_indexes参数限制每分钟记录条数,避免刷盘。

    用mysqldumpslow分析日志,找出TOP SQL

    日志文件是纯文本,直接打开会发现里面堆满了查询记录,人工翻找非常低效。MySQL自带的mysqldumpslow工具能把相似的SQL语句归并成一组,统计出现次数、平均执行时间、扫描行数等,然后排序输出。这个工具一般在MySQL安装目录的bin下面,或系统PATH中,命令格式为:

    mysqldumpslow -s t -t 10 /var/log/mysql/mysql-slow.log

    -s t表示按总时间排序,-s c按计数排序,-s at按平均时间排序,-t 10表示只显示前10条。常用组合还有按平均耗时排序:

    mysqldumpslow -s at -t 10 /var/log/mysql/mysql-slow.log

    输出结果类似(数字和表名会被抽象成N和S,便于归并):

    Count: 20  Time=3.01s (60s)  Lock=0.00s (0s)  Rows=1000.0 (20000)
      SELECT * FROM wp_posts WHERE post_status = 'N' ORDER BY post_date DESC LIMIT N, N
    

    Count表示该模式SQL出现次数,Time后第一个数是平均耗时,括号里是总耗时,Rows是平均扫描行数。如果某个查询Count高且平均耗时大,基本就是你的首要优化对象。分析时还要结合慢日志里记录的Rows_examined与Rows_sent,扫描行数远大于返回行数,说明索引没建好或SQL写法有问题。

    从慢SQL到优化落地,给出几条可操作建议

    定位到具体语句后,优化方向主要有四个。

    第一,加索引。对WHERE、ORDER BY、GROUP BY涉及的字段建立复合索引,但别让数据库索引泛滥,写多读少的表要特别克制。用EXPLAIN查看执行计划,确认type不是ALL(全表扫描),key字段有实际使用的索引,rows预估扫描行数应远小于表总行数。

    第二,改写SQL。避免SELECT *,只取必需字段;避免在WHERE子句中对字段做函数运算或隐式类型转换,例如WHERE DATE(create_time)='2026-09-01'会放弃索引,应改为范围查询create_time >= '2026-09-01' AND create_time < '2026-09-02'。分页深翻页问题,可以记录上一页最大ID,用WHERE id > ?代替LIMIT偏移量。

    第三,调整MySQL参数。如果日志里出现大量临时表或文件排序,可适当增大sort_buffer_size、join_buffer_size,但它们是会话级参数,设太大会浪费内存;查询缓存已在新版MySQL中废弃,不建议依赖。

    第四,处理高频重复查询。同一段慢SQL每分钟执行几十次,往往是程序里缺少缓存。用Redis把热点数据缓存起来,或者把复杂统计查询的结果物化到一张汇总表,定时刷新。

    最后提醒:慢查询日志本身也会带来磁盘I/O开销,定位问题后记得关闭或调大阈值,或者利用pt-query-digest这类工具做更细的分析。日志文件要配合logrotate定期切割,防止单个文件无限增长。MySQL版本不同,参数默认值有差异,具体以官方文档和当前环境为准。

    数据库性能优化是持续过程,不是改一条SQL就一劳永逸。借助慢查询日志建立基线,每次上线功能后对比同比数据,才能让网站长期保持稳定响应。

    继续阅读

    📑 📅
    自建网站状态监控:Uptime Kuma部署与告警配置 2026-09-10
    带宽跑满找元凶:iftop、nethogs与tcpdump排查详解 2026-09-10
    WordPress被挂马后的排查与清理:从文件到数据库的完整路径 2026-09-10
    访问日志不会看?goaccess与awk帮你快速定位异常请求 2026-09-09
    Nginx伪静态规则从零配置:WordPress与ThinkPHP的rewrite写法详解 2026-09-09
    Nginx 502/504 排查:从错误日志到PHP-FPM进程池状态 2026-09-10
    宝塔面板安全加固:面板端口、安全入口、SSL与登录告警设置 2026-09-11
    服务器磁盘被写满的排查流程:df与du定位、日志切割与清理注意事项 2026-09-11
    HTTPS证书有效却提示不安全:混合内容的定位与批量修复 2026-09-12
    phpMyAdmin导入大SQL超时:参数调整与命令行导入 2026-09-12