索引设计与调优
索引类型
复合索引与 ESR 规则
复合索引同样遵循「最左前缀」。字段顺序按 ESR 排列:
- E(Equality) 等值字段放最前
- S(Sort) 排序字段居中
- R(Range) 范围字段放最后
Tip
ESR 与关系型联合索引「等值在前、范围在后」的思想一致,额外强调排序字段的位置。排序方向也要与索引一致:{ createdAt: -1 } 对应索引 -1,反向排序(全字段取反)也能用索引,但混合方向(一个升一个降)在 MongoDB 中需要注意索引方向定义。
覆盖查询
查询字段与返回字段都在索引中时,无需读取文档(totalDocsExamined: 0),效率最高:
用 explain() 分析
关注指标:
理想情况:IXSCAN + nReturned ≈ totalKeysExamined ≈ totalDocsExamined(覆盖查询时 DocsExamined = 0)。
Warning
若 totalDocsExamined 远大于 nReturned,说明索引选择性差或未覆盖;若出现 SORT / SORT_KEY_GENERATOR 阶段,说明排序未用索引,会占用大量内存。COLLSCAN 出现在大集合上通常是严重问题。
索引代价与维护
- 每个索引都占用内存与磁盘,并拖慢写入。
- 删除无用索引:
db.coll.dropIndex("name")。 - 查看索引使用情况:
Tip
定期用 $indexStats 找出 accesses.ops = 0 的索引并清理。索引不是越多越好——尤其在写多读少的集合上,多余索引会显著拖慢写入。
小结
- 复合索引按 ESR(等值 → 排序 → 范围)设计字段顺序。
- 覆盖查询(
totalDocsExamined = 0)性能最佳。 - 用
explain("executionStats")判断是否IXSCAN、扫描是否高效。 - 定期审计并清理无用索引,控制写入成本。