MongoDB在Linux上的索引优化技巧
通过explain()方法分析查询执行计划(如db.collection.find(query).explain("executionStats")),了解查询是否使用了索引、扫描文档数量、返回结果大小等指标,明确需要优化的查询场景。针对频繁查询的字段(如username、email)或组合条件(如age > 25 AND status = "active")创建索引,避免为不常用的字段创建索引。
复合索引的字段顺序直接影响查询效率,应遵循**等值(Equality)→ 排序(Sort)→ 范围(Range)**的ESR规则。例如,对于查询{ age: 25, name: "Bob", createTime: { $gt: ISODate("2025-01-01") } },复合索引应设计为{ age: 1, name: 1, createTime: 1 }(age为等值查询,name为排序字段,createTime为范围查询),这样能最大化索引利用率。
若查询的所有字段(包括过滤、排序、返回字段)均包含在索引中,MongoDB可直接从索引中获取数据,无需访问文档本身(称为“覆盖查询”)。例如,索引{ name: 1, age: 1 }可支持查询{ name: "Alice" }并返回{ name: 1, age: 1 }(需排除_id字段或将其加入索引)。通过explain()的totalDocsExamined字段(值为0表示覆盖查询)验证是否生效。
使用db.collection.getIndexes()查看集合中的所有索引,定期清理不再使用的索引(如历史遗留的测试索引、不再查询的字段索引)。索引会占用磁盘空间并增加写入开销(每次插入、更新数据时需维护索引),可通过db.collection.dropIndex("indexName")删除冗余索引。
当查询优化器未选择最佳索引时(如因统计信息不准确),可使用hint()方法强制指定索引。例如,db.collection.find(query).hint({ age: 1, name: 1 })强制使用{ age: 1, name: 1 }索引。需谨慎使用,避免人为干预导致性能下降(仅在优化器选择错误时使用)。
随着数据的增删改,索引会产生碎片(索引数据分散在磁盘上),导致查询性能下降。使用db.collection.reIndex()命令重建索引,整理碎片并优化索引结构。建议在业务低峰期执行(重建索引会锁表,影响写入操作)。
通过$indexStats聚合管道(如db.collection.aggregate([{ $indexStats: {} }]))获取索引的使用频率(accesses.ops表示索引被访问的次数)、查询时间等指标,识别未使用或使用率低的索引并及时删除。也可使用MongoDB Compass、Ops Manager等工具可视化监控索引性能。
选择性高的字段(唯一值多,如email、userID)创建索引能更有效地过滤文档,提升查询效率。避免为低选择性字段(如gender、status,唯一值少)单独创建索引(除非该字段是查询的核心条件)。