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_logONlong_query_time1即表示配置生效。

三、定位慢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. 典型问题示例

如果typeALL(全表扫描)、keyNULLrows数值很大,说明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 = '北京';

优化步骤:

  1. 分析执行计划

    EXPLAIN SELECT * FROM user WHERE age > 20 AND city = '北京';
    

    发现type=ALL(全表扫描)、key=NULL(未用索引)。

  2. 创建复合索引

    -- 按“等值条件在前,范围条件在后”创建复合索引
    CREATE INDEX idx_user_city_age ON user(city, age);
    
  3. 优化SQL写法(去掉SELECT *):

    SELECT id, name, age, city FROM user WHERE age > 20 AND city = '北京';
    
  4. 验证优化效果
    再次执行EXPLAIN,type变为rangekeyidx_user_city_agerows大幅减少,执行时间降至0.01秒。

总结

  1. 抓慢SQL:开启慢查询日志(设置合理阈值,如1秒),用mysqldumpslow快速定位核心慢SQL。
  2. 分析慢SQL:通过EXPLAIN查看执行计划,重点关注typekeyrowsExtra字段。
  3. 优化核心:优先创建合适的索引(避免失效),优化SQL写法(减少扫描行数、避免全表扫描),大数据量场景可考虑分库分表/读写分离。

通过以上步骤,你可以系统性地识别、分析并优化MySQL慢SQL,显著提升数据库性能。

posted @ 2026-02-09 12:41  wuyingchun1987  阅读(2)  评论(0)    收藏  举报