- Published on
Mongodb Index 优化实践
- Authors
 - Name
- Shelton Ma
 
 
1. Mongodb 索引优化过程
1. 复合索引顺序优化: 如何尽可能命中更多索引
- 首先创建一些组合索引/单列索引, 然后执行 - explain()
- 在 - queryPlanner中查看- winningPlan是否符合预期, 如果在- stage: 'IXSCAN',- indexName:没有使用预期的索引, 说明说明不符合最优查询, 可以根据索引中各字段的分布规律/字段类型等特征排序
- 如果选择了一些更短的索引, 而不是选择命中最多的索引, 可以尝试将最多索引按照最短索引的顺序重新生成 
- 如果mongodb发生索引误判, 可以强制执行来对比查询效果, 但不建议长期使用 - db.SecurityAlert.find({ attackStatus: 1, organization: "ABC" }) .hint({ attackStatus: 1, organization: 1 }) .explain("executionStats")
2. 查询优化器对大范围查询 (lte, $in) 可能直接选择全表扫描
3. 使用索引覆盖 (Covered Query), 确保索引包含查询字段和返回字段,避免回表 (fetch)
在查看explain("executionStats")时, 如果stage存在fetch, 则说明发生了回表
2. 背景介绍
Query Planner 选择最优索引,而非最多索引
MongoDB 的查询优化器 不会选取命中最多索引的查询计划,而是根据 查询代价 (Cost-Based Optimization, CBO) 选择执行效率最高的索引。即使某个查询命中了多个索引,它也可能只选用一个最优索引,甚至排除所有命中的索引,原因如下
- 索引扫描成本:查询优化器计算索引扫描的扫描键数 (keysExamined) 和 返回文档数 (docsExamined),如果某个索引的扫描代价更低,即使它命中字段更少,MongoDB 也可能优先选择它。
- 索引覆盖率:如果某个索引可以 覆盖查询 (covered query),MongoDB 更倾向于使用它,而不是命中多个索引但仍需回表 (fetch documents) 的情况。
- 查询的选择性 (Selectivity):- 高选择性:如果索引能大幅减少查询结果集(如 { field: 1 }索引在 field=5 仅返回 1% 的数据),则 MongoDB 更倾向于使用它。
- 低选择性:如果索引返回的数据量太大(如 field: { $gt: 1 }返回 90% 数据),MongoDB 可能会选择全表扫描 (COLLSCAN) 而排除所有索引。
 
- 高选择性:如果索引能大幅减少查询结果集(如