慢sql优化需按定位→分析→调整路径执行:先用慢日志和性能视图定位问题sql,再通过explain关注type、extra、rows三类信息读懂执行计划,最后结合索引优化、sql重写、结构优化等手段针对性改进,并验证效果与持续监控。

慢SQL优化不是靠猜,而是有一套可落地的分析路径:先定位问题SQL,再分析执行计划,最后针对性调整。核心是理解数据库如何执行你的语句,而不是盲目加索引或改写。
一、快速定位慢SQL
生产环境不能靠日志逐条翻,要借助数据库自带的慢查询日志和性能视图:
- MySQL开启slow_query_log,设置long_query_time(建议0.1~1秒),配合log_queries_not_using_indexes捕获未走索引的查询
- PostgreSQL启用log_min_duration_statement,设为100ms以上,并开启log_statement = 'mod'辅助判断上下文
- 用pt-query-digest(MySQL)或pg_stat_statements(PostgreSQL)聚合分析,优先看Rows_examined/Rows_sent比值高、Execution time长、Frequency高的SQL
二、读懂执行计划(EXPLAIN)
不看执行计划就调优,等于蒙眼修车。重点关注三类信息:
- Type列:从system → const → eq_ref → ref → range → index → ALL,越靠后扫描范围越大;出现ALL(全表扫描)或index(全索引扫描)需警惕
- Extra列:含Using filesort(排序未走索引)、Using temporary(临时表)、Using join buffer(非驱动表关联缓存)说明有性能瓶颈
- Rows列:预估扫描行数,若远大于实际返回行数(如查1条却扫10万行),说明索引失效或选择性差
三、常见优化手段与适用场景
优化不是“加索引”三个字能概括的,要匹配具体瓶颈:
- 索引优化:联合索引遵循最左前缀原则,把高频等值条件放前面,范围查询(>, )放最后;避免在索引列上做函数操作(如WHERE YEAR(create_time) = 2024)
- SQL重写:用EXISTS替代IN子查询(尤其子查询结果大时);分页深翻用游标方式(WHERE id > last_id ORDER BY id LIMIT 20)替代OFFSET
- 结构优化:大字段(text/blob)单独拆表;冷热数据分离;频繁统计类查询考虑物化视图或汇总表
- 配置协同:适当调大sort_buffer_size、join_buffer_size(注意别超内存),但治标不治本,优先解决执行逻辑问题
四、验证与持续监控
优化后必须验证效果,且防止“好了又坏”:
- 用EXPLAIN ANALYZE(PostgreSQL)或EXPLAIN FORMAT=JSON(MySQL 8.0+)看真实执行耗时与行数,对比优化前后
- 在业务低峰期压测,观察QPS、CPU、IOPS变化,确认无副作用(如新索引拖慢写入)
- 将优化后的SQL加入监控白名单,结合APM工具(如SkyWalking、Datadog)追踪其P95响应时间趋势










