MongoDB 覆盖索引查询(Covered Query)
在 MongoDB 中,覆盖索引查询(Covered Query)是指查询所需的所有字段都可以直接从索引中获取,MongoDB 无需扫描文档(Documents),从而提高查询性能。
1. 覆盖索引查询的特点
- 查询字段全部在索引中 → 避免访问实际文档,减少 I/O。
- 索引必须包含所有查询字段(包括
find条件字段、projection返回字段)。 - _id 字段默认存在索引,如果查询结果不包含
_id,可能需要显式排除它。
2. 创建覆盖索引
示例:创建集合
db.products.insertMany([
{ _id: 1, name: "Laptop", category: "Electronics", price: 1200 },
{ _id: 2, name: "Phone", category: "Electronics", price: 800 },
{ _id: 3, name: "Table", category: "Furniture", price: 150 }
])
① 创建索引
创建组合索引,包含 category 和 price 字段:
db.products.createIndex({ category: 1, price: 1 })
② 使用覆盖索引查询
查询 category 和 price,并排除 _id(避免扫描文档):
db.products.find({ category: "Electronics" }, { category: 1, price: 1, _id: 0 })
💡 为什么排除 _id?
_id默认有索引,但不在{ category: 1, price: 1 }组合索引内,MongoDB 需要访问文档来获取_id,导致查询无法完全覆盖索引。
3. 使用 explain() 验证
可以使用 .explain("executionStats") 检查查询是否是覆盖索引查询:
db.products.find({ category: "Electronics" }, { category: 1, price: 1, _id: 0 }).explain("executionStats")
查看 explain 结果中的 "stage":
"stage": "PROJECTION_COVERED"
如果 "stage": "PROJECTION_COVERED",则表示完全使用索引,查询无需访问文档。
4. 覆盖索引 vs. 非覆盖索引查询
| 查询方式 | 是否使用索引 | 是否访问文档 | 适用场景 |
|---|---|---|---|
| 普通索引查询 | 仅用于查找 | 需要访问文档 | 查询字段较多 |
| 覆盖索引查询 | 直接获取结果 | 无需访问文档 | 查询字段较少,提高性能 |
5. 覆盖索引的优化技巧
✅ 使用组合索引(Compound Index),确保查询字段全部包含在索引中。
✅ 排除 _id 字段(如果不在索引内),避免额外的文档扫描。
✅ 适用于只查询少量字段的场景,例如统计、列表展示等。
6. 总结
- 覆盖索引查询可以显著提高查询性能,避免文档扫描,减少 I/O。
- 必须确保查询的字段都在索引中,否则 MongoDB 仍然会访问文档。
- 使用
.explain("executionStats")检查是否是覆盖索引查询,关键是"stage": "PROJECTION_COVERED"。
更多详细内容请关注其他相关文章!