跳至内容

数据库索引优化实战

2026-05-10

EXPLAIN 是 DBA 的眼睛。看 type 字段从 ALL 变成 ref 是最有成就感的事。

从慢查询开始

一切优化从定位问题开始。打开 MySQL 的慢查询日志(slow_query_log),设置 long_query_time = 0.1,跑一段时间后分析。PostgreSQL 用 pg_stat_statements 扩展,同样有效。

拿到慢查询,先 EXPLAIN 看执行计划。关注几个关键字段:

字段含义目标
type访问类型至少到 range,最好到 ref/const
key使用的索引不为 NULL
rows扫描行数越小越好
Extra额外信息避免 Using filesort / Using temporary

最左前缀原则

联合索引是最容易出错的地方。假设索引是 (a, b, c)

  • WHERE a = 1 ✅ 用到索引
  • WHERE a = 1 AND b = 2 ✅ 用到索引
  • WHERE b = 2 ❌ 用不到
  • WHERE a = 1 AND c = 3 ⚠️ 只用到了 a 列

排序也受这个规则约束。ORDER BY a, b 没问题,ORDER BY b, c 就需要额外排序。

覆盖索引

如果查询需要的所有列都在索引里,就不需要回表取数据。Extra 列显示 Using index 就是覆盖索引。对一个高频查询,覆盖索引能减少大量随机 I/O。

代价是索引变大了。不要为了覆盖索引把所有列都塞进索引——算一笔写入性能和存储空间的账。

真实案例

某个订单列表查询,原始 SQL 跑了 8 秒。EXPLAIN 一看,type: ALL,全表扫描 200 万行。加了 (user_id, created_at) 联合索引后,type: ref,扫描 20 行,耗时 12ms。

索引不是越多越好——每个索引都会拖慢写入速度并占用磁盘空间。建索引前问自己:这个查询的执行频率值得一个索引吗?