1. 什么是慢查询
MySQL 慢查询本质是“执行时间超过阈值的 SQL”,定位它靠慢查询日志 + 分析工具 + EXPLAIN,优化核心则是消除全表扫描、减少回表、避免排序/临时表与大事务阻塞。
MySQL 会把执行时间超过long_query_time的 SQL 记录到慢查询日志里,默认阈值是10 秒,但生产环境通常建议设为0.5~1 秒。 慢查询的危害主要有:
占用 CPU、内存、I/O;
持有锁时间变长,阻塞其他事务;
接口响应变慢,甚至触发超时。
2. 如何开启慢查询日志
可以在my.cnf中永久配置,也可以动态开启。
[mysqld] slow_query_log = 1 slow_query_log_file = /var/log/mysql/mysql-slow.log long_query_time = 1 log_queries_not_using_indexes = 1动态开启:
SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1; SET GLOBAL log_queries_not_using_indexes = 'ON';3. 慢查询日志关键字段
每条记录通常包含:
| 字段 | 含义 | 判断点 |
|---|---|---|
Query_time | 执行耗时 | 超过阈值才会被记录 |
Lock_time | 锁等待时间 | 占比高说明被锁阻塞 |
Rows_sent | 返回行数 | 实际返回给客户端的数据量 |
Rows_examined | 扫描行数 | 远大于返回行数,通常说明索引缺失或失效 |
如果Rows_examined很大,但Rows_sent很小,基本就是扫描了大量无用数据。
4. 怎么分析慢查询
常用三类方式:
mysqldumpslow:MySQL 自带工具,会把相似 SQL 归一化。mysqldumpslow -s t -t 10 /var/log/mysql/mysql-slow.log
pt-query-digest:Percona Toolkit 工具,报告更细,适合生产排查。pt-query-digest /var/log/mysql/mysql-slow.log
SHOW FULL PROCESSLIST:看当前正在执行的 SQL,适合排查“此刻正在卡”的问题。
5. 拿到慢 SQL 后怎么定位(explain)
如何使用 EXPLAIN :
在你要分析的 SELECT 语句前,加上 EXPLAIN 关键字即可: EXPLAIN SELECT 字段列表 FROM 表名 WHERE 条件; 执行后,会返回一个结果集,里面包含了 MySQL 执行这条 SQL 的详细信息。
故先用EXPLAIN看执行计划:
EXPLAIN SELECT * FROM orders WHERE user_id = 1001 AND status = 'PAID';
重点看:
type:
ALL是全表扫描,必须优化;key:为
NULL表示没走索引;rows:预估扫描行数,越大越危险;
Extra:出现
Using filesort、Using temporary通常说明有额外排序或临时表。
关键字段解读
(1)possible_keys 与 key possible_keys:MySQL 认为这条 SQL 可能会用到的索引。
key:MySQL 实际执行时真正用到的索引。 ==> 如果 key 为 NULL,说明没有使用任何索引,大概率是慢查询的原因。 如果 possible_keys 有值但 key 为 NULL,说明索引失效或优化器认为全表扫描更快。
(2)key_len表示使用的索引长度。
(3)type代表了 MySQL 在表中找到所需行的方式,性能从好到差排序为: NULL > system > const > eq_ref > ref > range > index > ALL ==》 const / eq_ref:性能最好,通常是通过主键或唯一索引查询,最多返回一行。 ref:使用普通索引进行查询。 range:范围查询,如 BETWEEN、IN、> 等。 index:扫描整个索引树,但不回表。ALL:全表扫描,性能最差,是慢查询的重灾区。
(4)Extra 包含了一些额外的优化信息,常见的有: Using where; Using Index:
最理想的情况,使用了索引,并且所需数据都在索引中,不需要回表查询。Using index condition:使用了索引,但需要回表查询数据。Using filesort / Using temporary:需要额外的排序或创建临时表,性能较差,需要重点优化。
总结:
SQL语句执行很慢,如何分析呢?
==?》 可以采用MySQL自带的分析工具EXPLAIN,即通过explain select的结果。
通过key和key_len检查是否命中了索引l(索引本身存在是否有失效的情况)
通过type字段查看sql是否有进一步的优化空间,是否存在全索引扫描或全盘扫描
通过extra建议判断,是否出现了回表的情况,如果出现了,可以尝试添加索引或修改返回字段来修复