mysql慢查询异常如何处理_mysql性能问题定位

来源:这里教程网 时间:2026-02-28 20:45:32 作者:

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

很多情况下你以为开了慢查询,其实只是配置写了但没 reload 或根本没生效。关键看三件事:

slow_query_log
必须为
ON
slow_query_log_file
路径可写且 MySQL 进程有权限,
long_query_time
值要合理(比如设成
1
而不是默认的
10
,否则多数业务慢 SQL 都不会记录)。

执行这条命令验证:

SHOW VARIABLES LIKE 'slow_query_log';

如果返回

OFF
,光改配置文件没用,得执行:

SET GLOBAL slow_query_log = ON;

注意:该命令重启后失效,必须同步更新

my.cnf
中的
[mysqld]
段落。

long_query_time
是按秒计的浮点数,设
0.5
表示记录所有超过 500ms 的查询
MySQL 5.7+ 支持
log_queries_not_using_indexes
,但开启后日志量暴增,仅调试期临时启用
日志文件路径若为相对路径(如
slow.log
),实际会写到
datadir
下,不是当前目录

用 pt-query-digest 快速定位 Top SQL

直接打开慢日志看文本效率极低。

pt-query-digest
是 Percona Toolkit 中最实用的分析工具,它能聚合、排序、统计响应时间分布,并给出索引建议。

基础用法:

pt-query-digest /var/lib/mysql/slow.log

常用参数:

--limit 10
:只看耗时最高的 10 条
--filter '$event->{Bytes} > 1024'
:过滤掉返回数据量太小的查询(可能只是 debug 语句)
--since "2024-06-01 00:00:00"
:限定时间范围,避免全量扫描
--no-report
+
--print
:输出原始 SQL,方便复制进客户端重跑

注意:

pt-query-digest
默认按 Query Time 排序,但有时
Lock Time
Rows_examined
更能暴露问题——比如一条 SQL 执行快但锁了 3 秒,或扫描了 200 万行只返回 1 行。

EXPLAIN 结果里哪些字段最值得盯

拿到可疑 SQL 后,别急着加索引,先看

EXPLAIN FORMAT=TRADITIONAL
输出。重点关注这四个字段:

type
:值为
ALL
index
就是全表/全索引扫描,基本要优化;
range
ref
const
较健康
key
:显示实际使用的索引名。如果为
NULL
,说明没走索引(可能是隐式类型转换、函数包裹字段、or 条件未命中索引等)
rows
:预估扫描行数。如果远大于结果集行数(比如
rows=124800
SELECT COUNT(*)
只有 1300),说明索引选择性差或统计信息过期
Extra
:出现
Using filesort
Using temporary
是严重信号,意味着排序/分组无法利用索引完成

执行前记得更新统计信息:

ANALYZE TABLE orders;

为什么加了索引查询还是慢

常见原因不是没索引,而是索引没被用上,或者用了但效果差。典型场景包括:

WHERE 条件中对字段做了函数操作,例如
WHERE YEAR(create_time) = 2024
→ 改成
WHERE create_time BETWEEN '2024-01-01' AND '2024-12-31'
字符集不一致导致隐式转换,比如
utf8mb4
列和
utf8
参数比较 → 统一字符集,或显式
COLLATE
联合索引顺序错位,比如索引是
(a,b,c)
,但查询只用了
b = ?
c = ?
→ 无法命中该索引
MySQL 认为走索引比全表扫更慢(比如表小、缓存热),强制走索引可用
FORCE INDEX
测试,但属临时手段

复杂查询建议拆成多个简单查询,尤其涉及多表 JOIN + GROUP BY + LIMIT 的场景——MySQL 优化器容易选错执行计划,而应用层合并结果往往更可控。

相关推荐