SQL慢查询指的是执行时间超过预设阈值的SQL语句,这类语句会占用大量数据库资源,导致接口响应变慢甚至系统卡顿。排查和解决慢查询是数据库性能优化的重要环节,需要结合日志分析和针对性的优化操作来完成。

一、慢查询日志的开启与查看
慢查询日志是排查问题的核心依据,首先需要确保数据库的慢查询日志功能已开启,不同数据库的开启方式略有差异,以MySQL为例,相关配置如下:
-- 查看慢查询日志是否开启 SHOW VARIABLES LIKE 'slow_query_log'; -- 开启慢查询日志 SET GLOBAL slow_query_log = 'ON'; -- 设置慢查询阈值,单位秒,这里设置为1秒,执行超过1秒的SQL会被记录 SET GLOBAL long_query_time = 1; -- 查看慢查询日志存储路径 SHOW VARIABLES LIKE 'slow_query_log_file';
开启后,所有执行时间超过long_query_time设置的SQL语句都会被记录到指定的日志文件中,我们可以通过查看日志文件获取慢查询的相关信息。
二、慢查询日志分析要点
拿到慢查询日志后,需要重点关注以下几类信息来定位问题:
- 执行时间:确认SQL的具体执行耗时,判断是否符合慢查询的判定标准。
- 扫描行数:执行过程中扫描的数据行数,扫描行数过多通常是性能差的主要原因。
- 返回行数:最终返回给客户端的数据行数,如果扫描行数远大于返回行数,说明查询效率很低。
- SQL语句内容:完整的SQL语句,用于后续分析语句本身的问题。
如果是MySQL数据库,还可以使用自带的mysqldumpslow工具对日志进行汇总分析,快速找到出现频率最高的慢查询:
# 分析慢查询日志,按查询次数排序,显示前10条 mysqldumpslow -s c -t 10 /var/lib/mysql/slow.log # 按查询时间排序,显示前10条 mysqldumpslow -s t -t 10 /var/lib/mysql/slow.log
三、完整的SQL慢查询优化流程
1. 定位问题SQL
通过慢查询日志筛选出需要优化的SQL语句,优先处理执行频率高、耗时长的语句,这类语句对系统性能的影响最大。
2. 分析SQL执行计划
使用EXPLAIN命令查看SQL的执行计划,判断索引是否生效、表的关联方式是否合理:
-- 查看指定SQL的执行计划 EXPLAIN SELECT * FROM user WHERE age > 18 AND city = '北京';
执行计划中的关键字段说明:
| 字段名 | 含义 |
|---|---|
| type | 访问类型,从好到坏依次为system>const>eq_ref>ref>range>index>ALL,出现ALL表示全表扫描,需要优化 |
| key | 实际使用的索引,如果为NULL表示没有使用索引 |
| rows | 预估扫描的行数,数值越小越好 |
| Extra | 额外信息,出现Using filesort、Using temporary表示需要额外排序或临时表,性能较差 |
3. 针对性优化操作
(1)索引优化
如果执行计划中未使用索引,需要根据查询条件添加合适的索引:
-- 为user表的city和age字段添加联合索引 ALTER TABLE user ADD INDEX idx_city_age (city, age);
注意避免索引失效的场景,比如对索引字段做函数操作、使用LIKE '%xxx'左模糊匹配、查询条件中使用OR且部分字段无索引等。
(2)SQL语句改写
对不合理的SQL语句进行改写,比如避免SELECT *,只查询需要的字段;减少子查询,改用关联查询;拆分大批量操作的SQL,避免长事务。
-- 优化前 SELECT * FROM user WHERE id IN (SELECT user_id FROM order WHERE amount > 100); -- 优化后 SELECT u.id, u.name FROM user u INNER JOIN order o ON u.id = o.user_id WHERE o.amount > 100;
(3)数据库配置调整
如果单条SQL优化后效果仍不理想,可以适当调整数据库配置,比如增大innodb_buffer_pool_size让更多数据缓存在内存中,调整max_connections避免连接数不足等,配置调整需要结合服务器实际资源情况。
4. 优化后验证
优化完成后,再次执行原SQL语句,查看执行时间是否下降,执行计划是否改善,同时观察慢查询日志中是否不再出现该条语句,确认优化生效。
四、慢查询日常预防建议
除了问题出现后的排查优化,日常开发中也可以做好预防工作:开发阶段就关注SQL的执行效率,上线前对核心接口做性能测试,定期分析慢查询日志,及时清理无用的索引避免影响写入性能。