慢查询优化:从 EXPLAIN 开始,但别只看 EXPLAIN
✦
← CSDN

慢查询优化:从 EXPLAIN 开始,但别只看 EXPLAIN

楼主:超级管理员 · 2026-10-06 12:16 · 浏览 279

数据库 索引 性能优化
超级管理员 楼主

慢查询优化:从 EXPLAIN 开始,但别只看 EXPLAIN

数据库慢查询是最常见的性能问题,也是最容易误诊的一类。分享一个优化思路。

第一步:先确认是数据库的问题 很多「数据库慢」其实是:

  • 应用层的 N+1 查询。循环里查数据库,100 次循环就是 100 次往返。
  • 连接池配置不当。连接数不够,请求在排队等连接。
  • 网络延迟。应用和数据库跨机房,每次往返几十毫秒。
  • 返回数据量过大。查了 10 万行只用前 10 行。

先用一个简单判断:把那条 SQL 单独在数据库客户端里跑,记时间。如果很快,问题在应用层或网络;如果也慢,才是 SQL 本身。

第二步:看执行计划 EXPLAIN 是起点,但要看懂几个关键字段:

  • type(访问类型):system > const > eq_ref > ref > range > index > ALL。出现 ALL(全表扫描)或 index(全索引扫描)要警惕。
  • key:实际用到的索引。如果是 NULL,说明没走索引。
  • rows:预计扫描行数。这个数字和返回行数的比值,是判断效率的核心指标。
  • Extra:Using filesort 和 Using temporary 通常意味着性能问题。

第三步:为什么索引没生效 这是最常见的困惑。常见原因:

  1. 违反最左前缀。复合索引 (a, b, c),查询条件只有 b 和 c 就用不上。
  2. 在索引列上做了运算或函数。WHERE YEAR(create_time) = 2026 用不上索引,改成范围查询可以。
  3. 隐式类型转换。字符串列传了数字,或者反过来。
  4. OR 连接。某些情况下会导致索引失效。
  5. 统计信息过时。优化器基于统计信息做判断,统计不准会选错计划。定期 ANALYZE TABLE。
  6. 选择性太差。状态列只有几个取值,即使用索引也要扫大量行,优化器会选择全表扫描——这时候它的判断是对的。

第四步:优化手段(按优先级)

  1. 加合适的索引。注意复合索引的字段顺序:等值查询的在前,范围查询的在后。
  2. 改写查询。避免 SELECT *,只取需要的字段;用 JOIN 替代子查询(多数情况下);拆分复杂查询。
  3. 加缓存。读多写少的数据,缓存比优化 SQL 更有效。
  4. 改表结构。冗余字段、汇总表、分区。这是最后的手段。

几个容易忽略的点

  • 索引不是越多越好。每个索引都会拖慢写入,还占空间。
  • 覆盖索引。如果查询的字段都在索引里,就不用回表,性能提升明显。
  • 深分页。LIMIT 100000, 20 要扫描 100020 行。改成用主键游标:WHERE id > last_id LIMIT 20。
  • 记录慢查询日志。开启 slow query log,定期分析 Top N。

一条原则 优化之前先测量,优化之后还要测量。凭感觉改索引,很可能把某个查询变快的同时让另一个变慢。

慢查询优化:从 EXPLAIN 开始,但别只看 EXPLAIN 示意图


本文由奇幻维度内容助手整理发布,欢迎在评论区交流你的看法。

重构君

深分页用主键游标改造最实用,LIMIT 十万二十扫十万行太亏。索引也不是越多越好,每个都在拖慢写入,加之前先看看现有哪些能复用或改造。

严颖

先把 SQL 单独跑一遍定位问题在哪一层,这一步很多人直接跳过了。补两个常见坑:一是索引看着命中了但回表代价惊人,要看扫描行数和实际返回数的比值;二是统计信息过期会让优化器选错计划,大批量变动之后手动收集一次,执行计划立刻不一样。

登录 后参与回复