MySQL慢查询指的是执行时间超过指定阈值的SQL语句,这类语句会占用大量数据库资源,导致整体业务响应变慢,需要针对性查找并优化。

开启MySQL慢查询日志
要查找慢查询,首先需要开启MySQL的慢查询日志功能,可以通过配置文件或者命令行临时开启。
配置文件开启方式
修改MySQL的配置文件my.cnf(Linux系统)或者my.ini(Windows系统),添加以下配置项:
[mysqld] # 开启慢查询日志 slow_query_log = 1 # 慢查询日志存储路径 slow_query_log_file = /var/lib/mysql/slow.log # 慢查询阈值,单位秒,这里设置为1秒,执行超过1秒的SQL会被记录 long_query_time = 1 # 记录未使用索引的查询 log_queries_not_using_indexes = 1
修改完成后重启MySQL服务即可生效。
命令行临时开启方式
如果需要临时开启慢查询日志,不需要重启服务,可以执行以下SQL语句:
-- 开启慢查询日志 SET GLOBAL slow_query_log = 'ON'; -- 设置慢查询日志文件路径 SET GLOBAL slow_query_log_file = '/var/lib/mysql/slow.log'; -- 设置慢查询阈值,单位秒 SET GLOBAL long_query_time = 1; -- 开启未使用索引的查询记录 SET GLOBAL log_queries_not_using_indexes = 'ON';
查找慢查询语句
开启慢查询日志后,所有符合阈值的SQL语句都会被记录到指定的日志文件中,我们可以通过以下方式分析日志。
使用mysqldumpslow工具分析
MySQL自带了mysqldumpslow工具,可以快速汇总慢查询日志中的语句,常用命令如下:
# 查看慢查询日志中执行次数最多的10条语句 mysqldumpslow -s c -t 10 /var/lib/mysql/slow.log # 查看执行时间最长的10条语句 mysqldumpslow -s t -t 10 /var/lib/mysql/slow.log # 查看包含指定表的慢查询 mysqldumpslow -g "user_table" /var/lib/mysql/slow.log
直接查看慢查询日志
也可以直接打开慢查询日志文件查看原始记录,每条慢查询记录会包含执行时间、锁等待时间、返回行数、执行用户、具体SQL等信息,示例如下:
# Time: 2024-05-20T10:30:00.123456Z # User@Host: root[root] @ localhost [] Id: 123 # Query_time: 2.345 Lock_time: 0.123 Rows_sent: 10 Rows_examined: 100000 SET timestamp=1716196200; SELECT * FROM user_table WHERE user_name LIKE '%test%';
慢查询调优方法
找到慢查询语句后,可以根据不同的场景选择对应的调优方案。
索引优化
缺少合适索引是慢查询最常见的原因,可以通过EXPLAIN命令分析SQL的执行计划,判断是否需要添加索引。
-- 分析查询语句的执行计划 EXPLAIN SELECT * FROM user_table WHERE user_name = 'test_user';
如果执行计划中type字段为ALL,说明是全表扫描,需要给user_name字段添加索引:
-- 添加普通索引 CREATE INDEX idx_user_name ON user_table(user_name); -- 如果是唯一值字段,可以添加唯一索引 CREATE UNIQUE INDEX idx_user_id ON user_table(user_id);
SQL语句改写
部分慢查询可以通过改写SQL语句提升性能,比如避免SELECT *、减少LIKE '%xxx%'这种无法使用索引的写法、优化子查询为连接查询等。
原慢查询语句:
SELECT * FROM user_table WHERE user_name LIKE '%test%';
如果业务允许,可以改为前缀匹配,使用索引:
SELECT user_id,user_name FROM user_table WHERE user_name LIKE 'test%';
数据库参数调整
如果慢查询是因为数据库参数配置不合理,可以适当调整相关参数,比如innodb_buffer_pool_size设置过小会导致频繁磁盘IO,可以适当调大:
[mysqld] # 设置InnoDB缓冲池大小为系统内存的70%左右,根据服务器实际情况调整 innodb_buffer_pool_size = 4G
调优测试验证
调优完成后需要验证效果,我们可以对比调优前后的SQL执行时间。
首先执行原慢查询语句,记录执行时间:
-- 开启 profiling 用于统计SQL执行时间 SET profiling = 1; -- 执行原慢查询 SELECT * FROM user_table WHERE user_name LIKE 'test%'; -- 查看执行时间 SHOW PROFILES;
添加索引后再次执行相同的查询,查看执行时间,正常情况下执行时间会有明显下降。我们也可以通过EXPLAIN再次分析执行计划,确认已经不再全表扫描,而是使用了对应的索引。
| 优化阶段 | 执行时间(秒) | 扫描行数 | 执行计划type |
|---|---|---|---|
| 优化前 | 2.345 | 100000 | ALL |
| 添加索引后 | 0.012 | 100 | range |
通过对比可以看到,调优后SQL性能有了明显提升,慢查询问题得到解决。