mysql 慢sql分析
你想了解MySQL中慢SQL的全流程处理方法,包括如何开启慢查询日志、定位慢SQL、分析原因以及优化手段,对吧?慢SQL是数据库性能瓶颈的核心来源,下面我会从新手视角一步步讲解,确保你能落地实操。
一、什么是MySQL慢SQL
慢SQL指执行时间超过指定阈值的SQL语句(MySQL默认阈值是10秒,实际生产中一般设置为1秒)。这类SQL会占用大量数据库资源(CPU、IO、内存),导致数据库响应变慢,甚至引发系统卡顿。
二、开启慢查询日志(核心:先抓到慢SQL)
慢查询日志是MySQL记录慢SQL的核心功能,默认是关闭的,需要手动开启。
1. 临时开启(重启MySQL失效,适合测试)
登录MySQL客户端,执行以下命令:
-- 1. 开启慢查询日志(ON=开启,OFF=关闭)
SET GLOBAL slow_query_log = ON;
-- 2. 设置慢SQL阈值(单位:秒,这里设为1秒,即执行超1秒的SQL会被记录)
SET GLOBAL long_query_time = 1;
-- 3. 设置慢查询日志文件路径(可自定义,默认在数据目录下)
SET GLOBAL slow_query_log_file = '/var/lib/mysql/slow_query.log';
-- 4. 可选:记录未使用索引的SQL(即使执行时间没超阈值,也能发现索引问题)
SET GLOBAL log_queries_not_using_indexes = ON;
2. 永久开启(修改配置文件,重启生效)
编辑MySQL配置文件(不同系统路径不同:Linux一般是/etc/my.cnf或/etc/mysql/my.cnf,Windows是my.ini),添加/修改以下配置:
[mysqld]
# 开启慢查询日志
slow_query_log = ON
# 慢SQL阈值(秒)
long_query_time = 1
# 慢查询日志文件路径
slow_query_log_file = /var/lib/mysql/slow_query.log
# 记录未使用索引的SQL(可选)
log_queries_not_using_indexes = ON
# 可选:记录管理类语句(如ALTER、ANALYZE,默认不记录)
log_slow_admin_statements = ON
修改后重启MySQL:
# Linux重启命令
systemctl restart mysqld
# 或
service mysqld restart
3. 验证配置是否生效
执行以下SQL查看配置:
SHOW VARIABLES LIKE '%slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
输出中slow_query_log为ON、long_query_time为1即表示配置生效。
三、定位慢SQL(找到具体的慢查询语句)
开启慢查询日志后,执行一段时间业务操作,就能在日志文件中找到慢SQL,常用两种方式分析:
1. 直接查看慢查询日志
用文本编辑器打开日志文件(如/var/lib/mysql/slow_query.log),日志格式示例:
# Time: 2026-02-09T10:00:00.000000+08:00
# User@Host: root[root] @ localhost [] Id: 123
# Query_time: 5.20 Lock_time: 0.01 Rows_sent: 100 Rows_examined: 100000
SET timestamp=1749501600;
SELECT * FROM user WHERE age > 20;
关键字段说明:
Query_time:SQL执行时间(5.20秒,超过1秒阈值)Lock_time:锁等待时间Rows_sent:返回行数Rows_examined:扫描行数(扫描行数远大于返回行数,说明有优化空间)
2. 使用mysqldumpslow工具(推荐,更高效)
MySQL自带的mysqldumpslow工具可以统计慢日志,按执行时间、次数等排序,适合批量分析:
# 常用命令示例
# 1. 按执行时间排序,显示前10条慢SQL
mysqldumpslow -s t -t 10 /var/lib/mysql/slow_query.log
# 2. 按执行次数排序,显示前10条慢SQL
mysqldumpslow -s c -t 10 /var/lib/mysql/slow_query.log
# 3. 查找包含SELECT的慢SQL
mysqldumpslow -g "SELECT" /var/lib/mysql/slow_query.log
参数说明:
-s:排序规则(t=按时间,c=按次数,l=按锁时间)-t:显示前N条-g:匹配关键字(支持正则)
四、分析慢SQL(用EXPLAIN看执行计划)
找到慢SQL后,核心是分析其执行逻辑,MySQL的EXPLAIN关键字可以查看SQL的执行计划,定位索引失效、全表扫描等问题。
1. 使用方法
在慢SQL前加EXPLAIN即可:
EXPLAIN SELECT * FROM user WHERE age > 20;
2. 关键字段解读(新手重点看这5个)
| 字段 | 含义 |
|---|---|
| id | 执行顺序(数字越大越先执行,相同则从上到下) |
| type | 访问类型(核心!性能从好到差:ALL < index < range < ref < eq_ref < const) |
| key | 实际使用的索引(NULL表示未使用索引) |
| rows | 预估扫描行数(数值越大,性能越差) |
| Extra | 额外信息(如Using filesort=文件排序,Using temporary=临时表,均为性能问题) |
3. 典型问题示例
如果type是ALL(全表扫描)、key为NULL、rows数值很大,说明SQL存在严重性能问题。
五、慢SQL常见原因及优化方法
| 常见原因 | 优化方法 |
|---|---|
| 未创建索引/索引失效 | 1. 为查询条件字段创建合适索引(如age字段创建索引:CREATE INDEX idx_user_age ON user(age);) 2. 避免索引失效(如不使用SELECT *、不做字段函数运算:WHERE DATE(create_time) = '2026-02-09') |
| 全表扫描 | 1. 添加索引 2. 缩小查询范围(如加LIMIT、WHERE条件) |
| SELECT * 查所有字段 | 只查询需要的字段(如SELECT id, name FROM user WHERE age > 20;) |
| 大表排序/分组(Using filesort) | 1. 为排序字段创建索引 2. 减少排序数据量(先过滤再排序) |
| 关联查询(JOIN)效率低 | 1. 为JOIN关联字段创建索引 2. 小表驱动大表(INNER JOIN时小表放前面) |
| 分页查询(LIMIT 10000,10) | 1. 用主键分页(如WHERE id > 10000 LIMIT 10;) 2. 预查询主键再关联 |
六、优化示例(实战)
假设有一条慢SQL:
-- 执行时间5.2秒,全表扫描10万行
SELECT * FROM user WHERE age > 20 AND city = '北京';
优化步骤:
-
分析执行计划:
EXPLAIN SELECT * FROM user WHERE age > 20 AND city = '北京';发现
type=ALL(全表扫描)、key=NULL(未用索引)。 -
创建复合索引:
-- 按“等值条件在前,范围条件在后”创建复合索引 CREATE INDEX idx_user_city_age ON user(city, age); -
优化SQL写法(去掉SELECT *):
SELECT id, name, age, city FROM user WHERE age > 20 AND city = '北京'; -
验证优化效果:
再次执行EXPLAIN,type变为range、key为idx_user_city_age、rows大幅减少,执行时间降至0.01秒。
总结
- 抓慢SQL:开启慢查询日志(设置合理阈值,如1秒),用
mysqldumpslow快速定位核心慢SQL。 - 分析慢SQL:通过
EXPLAIN查看执行计划,重点关注type、key、rows、Extra字段。 - 优化核心:优先创建合适的索引(避免失效),优化SQL写法(减少扫描行数、避免全表扫描),大数据量场景可考虑分库分表/读写分离。
通过以上步骤,你可以系统性地识别、分析并优化MySQL慢SQL,显著提升数据库性能。
浙公网安备 33010602011771号