什么是 MySQL 慢查询?为什么需要排查
慢查询指的是执行时间超过预设阈值的 SQL 语句。一条设计不当的查询,可能单次就要几秒甚至几十秒,在并发场景下会迅速拖垮整个数据库连接池,让原本正常的网站出现页面加载缓慢、接口超时等问题。对于使用 WordPress、Discuz 或自建业务系统的站长来说,慢查询往往是"网站莫名其妙变卡"的第一嫌疑对象。
MySQL 提供了慢查询日志(Slow Query Log)功能,可以把执行时间超过阈值的语句完整记录下来。通过分析这些日志,我们能定位到具体是哪条 SQL、在哪个业务模块消耗了资源,再结合执行计划(EXPLAIN)进行针对性优化。整个过程不需要重启数据库,也不需要停机,普通站长在宝塔面板或命令行里就能完成。
第一步:开启慢查询日志
先登录服务器,通过命令行确认当前慢查询相关的参数状态:
mysql -u root -p
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
如果 slow_query_log 的值为 OFF,说明慢查询日志还没有开启。可以在 MySQL 命令行中临时开启(重启后会失效,适合先观察一段时间):
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL slow_query_log_file = '/var/log/mysql/mysql-slow.log';
SET GLOBAL long_query_time = 1;
上面的配置表示:执行时间超过 1 秒的语句都会被记录到指定日志文件中。如果希望永久生效,需要修改配置文件(通常是 /etc/my.cnf 或 /etc/mysql/my.cnf),在 [mysqld] 段落中加入对应的配置后重启 MySQL。注意:修改配置文件属于变更操作,建议先备份原配置文件,并选择业务低峰期重启,避免影响线上服务。

第二步:用 mysqldumpslow 分析慢查询日志
日志开启并运行一段时间后,文件里会积累大量记录。MySQL 自带了 mysqldumpslow 工具,可以按执行次数、总耗时等维度汇总分析:
# 按总耗时排序,查看前 10 条最耗时的查询
mysqldumpslow -s t -t 10 /var/log/mysql/mysql-slow.log
# 按出现次数排序,查看被调用最频繁的慢查询
mysqldumpslow -s c -t 10 /var/log/mysql/mysql-slow.log
输出的结果中,每条记录会显示执行次数、平均耗时、返回行数,以及经过参数化处理的 SQL 语句。重点关注两类语句:一是 Count 很高、平均耗时也不低的(调用频繁又慢),二是单次 Rows_examined(扫描行数)远大于 Rows_sent(返回行数)的(说明扫描了大量无用数据)。如果你的服务器装了宝塔面板,也可以在数据库页面的日志功能里直接查看慢日志内容,效果类似。
第三步:用 EXPLAIN 定位性能瓶颈
找到可疑 SQL 后,在语句前加上 EXPLAIN 关键字执行,可以查看这条查询的执行计划:
EXPLAIN SELECT * FROM wp_posts WHERE post_title = '示例标题';
重点关注几个字段:type(访问类型,出现 ALL 表示全表扫描,数据量大时需要优化);key(实际使用的索引,为 NULL 说明没有走索引);rows(预估扫描行数,越少越好)。常见的优化手段包括:给 WHERE、ORDER BY、JOIN 涉及的字段添加合适索引;避免在索引列上使用函数或隐式类型转换;避免 SELECT *,只查询需要的字段。
第四步:索引优化与常见改法
添加索引是最常见的优化方式,但要注意方法。给已有大量数据的表加索引会锁表并消耗资源,建议在低峰期执行:
# 为常用查询字段添加普通索引
ALTER TABLE wp_postmeta ADD INDEX idx_meta_key (meta_key);
# 验证索引是否生效
SHOW INDEX FROM wp_postmeta;
EXPLAIN SELECT * FROM wp_postmeta WHERE meta_key = '_thumbnail_id';
需要注意:索引并非越多越好。每个索引都会占用磁盘空间,并降低写入(INSERT/UPDATE)速度。一般建议单表索引数量控制在合理范围,优先为高频率查询条件建索引。修改表结构属于高风险操作,执行前务必先备份数据表,可以通过宝塔面板的数据库备份功能,或使用 mysqldump -u root -p 数据库名 > 备份文件.sql 完整导出。
常见问题 FAQ
问:慢查询日志文件越来越大,可以删除吗?
答:不建议直接删除文件。可以在 MySQL 命令行执行 SET GLOBAL slow_query_log = 'OFF'; 后清理或轮转日志文件,再重新开启。生产环境建议配置 logrotate 做自动轮转。
问:long_query_time 设置成多少合适?
答:一般业务系统建议从 1 秒开始观察;对响应速度要求高的接口型业务可以设为 0.5 秒。阈值设得太小会产生海量日志,太大则可能漏掉真正的问题语句,建议根据业务特点逐步调整。
问:加了索引还是慢怎么办?
答:先确认 EXPLAIN 中 key 字段是否真的用上了新索引。如果没用上,可能是查询条件中存在函数运算、隐式类型转换(如字符串列用数字比较),或优化器判断走索引反而更慢(回表代价高)。必要时可以改写 SQL,或考虑联合索引、覆盖索引等方案。
问:排查慢查询会影响线上业务吗?
答:开启慢查询日志本身开销很小,基本无感。但执行 ALTER TABLE 加索引、重启 MySQL 等操作会有锁表或中断风险,务必先备份、先评估业务影响,并在低峰期进行。
总结
MySQL 慢查询排查的完整链路是:开启慢查询日志 → 用 mysqldumpslow 汇总分析 → 用 EXPLAIN 定位瓶颈 → 通过索引和 SQL 改写优化。整个过程中,最重要的原则是"先备份、再变更、低峰期操作"。养成定期查看慢查询日志的习惯,往往能在用户投诉之前就把隐患解决掉。如果你在使用宝塔面板,也可以结合它自带的日志与备份功能,让整个排查流程更加省心。












暂无评论内容