SQL查询优化是数据库性能调优的核心工作,当系统中出现响应缓慢的查询时,需要按照规范的流程逐步定位问题并解决,避免盲目调整导致优化效果不明显甚至引发新的问题。

慢SQL的识别方式
要优化SQL首先需要找到慢SQL,常用的识别方式有以下几种:
- 开启数据库慢查询日志,设置合理的慢查询阈值,比如超过1秒的查询自动记录到日志中
- 通过数据库监控工具查看实时查询耗时,定位当前正在执行的慢查询
- 分析业务接口的响应时间,反向关联对应的数据库查询语句
慢SQL分析流程
1. 查看执行计划
执行计划是分析SQL性能的核心依据,不同数据库查看执行计划的语法略有差异,以MySQL为例:
-- 查看SQL语句的执行计划 EXPLAIN SELECT user_id, user_name FROM user_info WHERE age > 18 AND status = 1;
执行计划中的关键字段需要重点关注:
| 字段名 | 含义 | 优化参考 |
|---|---|---|
| type | 访问类型 | 尽量达到ref、eq_ref级别,避免ALL全表扫描 |
| key | 实际使用的索引 | 如果为NULL说明未使用索引,需要检查索引设计 |
| rows | 估算扫描行数 | 数值越小说明扫描的数据越少,性能越好 |
| Extra | 额外信息 | 出现Using filesort、Using temporary说明存在性能问题 |
2. 分析查询瓶颈
根据执行计划的结果定位具体问题:
- 如果是全表扫描,检查查询条件是否有合适的索引
- 如果扫描行数过多,检查索引是否失效,比如对索引字段使用函数、隐式类型转换
- 如果出现文件排序或临时表,检查排序、分组字段是否有索引支持
慢SQL优化方法
索引优化
索引是提升查询性能最有效的手段,优化时需要注意:
- 为查询条件的字段建立合适的索引,优先选择区分度高的字段
- 避免建立过多冗余索引,冗余索引会增加写入性能损耗
- 联合索引遵循最左前缀原则,将区分度高的字段放在前面
比如针对查询WHERE age > 18 AND status = 1,可以建立联合索引:
-- 建立联合索引 CREATE INDEX idx_age_status ON user_info(age, status);
SQL语句改写
不合理的语句写法也会导致性能问题,常见的改写方式:
- 避免使用
SELECT *,只查询需要的字段,减少数据传输和扫描开销 - 减少子查询的使用,尽量用关联查询替代
- 避免对索引字段做函数处理,比如
WHERE DATE(create_time) = '2024-01-01'可以改写为范围查询 - 合理使用分页,深度分页时可以用游标方式替代
LIMIT offset, size
深度分页优化示例:
-- 原始深度分页语句,offset过大时性能差 SELECT id, user_name FROM user_info ORDER BY id LIMIT 100000, 10; -- 优化后的游标分页语句 SELECT id, user_name FROM user_info WHERE id > 100000 ORDER BY id LIMIT 10;
其他优化方式
- 定期分析表,更新索引统计信息,避免执行计划走错索引
- 对于大表查询,可以考虑分库分表减少单表数据量
- 合理使用缓存,将高频查询的结果缓存到Redis中,减少数据库查询次数
优化验证
优化完成后需要再次执行SQL,查看执行计划和实际耗时,确认优化效果。如果优化后性能没有明显提升,需要重新回到分析流程,排查是否有遗漏的问题点。