MongoDB 查询分析(Query Analysis)
在 MongoDB 中,查询分析是优化查询性能的关键。我们可以使用 explain() 方法来获取查询的执行计划,分析索引使用情况、扫描的文档数量等,以优化数据库查询。
1. 使用 explain() 进行查询分析
MongoDB 提供 explain() 方法,它可以用于检查查询的执行计划,确定查询是否使用了索引,是否进行了全表扫描(COLLSCAN),以及查询的效率。
基本用法
db.collection.find({ 查询条件 }).explain()
三种模式
"queryPlanner"(默认):仅返回查询计划,不执行查询。"executionStats":执行查询并返回统计信息(推荐)。"allPlansExecution":返回所有可能的执行计划,并执行查询。
db.collection.find({ name: "Laptop" }).explain("executionStats")
2. explain() 结果解析
执行 explain("executionStats") 后,返回的 JSON 结构如下:
示例
{
"queryPlanner": {
"winningPlan": {
"stage": "COLLSCAN"
}
},
"executionStats": {
"nReturned": 1,
"totalKeysExamined": 0,
"totalDocsExamined": 1000,
"executionTimeMillis": 12
}
}
关键字段解析
| 字段 | 说明 |
|---|---|
"stage" | 查询执行的方式,如 COLLSCAN(全表扫描)、IXSCAN(索引扫描) |
"nReturned" | 返回的文档数量 |
"totalKeysExamined" | 查询使用的索引数量 |
"totalDocsExamined" | 查询扫描的文档数量(应尽量减少) |
"executionTimeMillis" | 查询执行时间(应尽量优化) |
如果 "stage": "COLLSCAN"(全表扫描),说明查询没有使用索引,应优化索引。
3. 如何优化查询
① 创建索引
如果查询是 COLLSCAN,可以创建索引提高查询性能。例如:
db.products.createIndex({ name: 1 })
然后再次执行 explain("executionStats"),如果 "stage" 变为 IXSCAN,说明索引已生效。
② 复合索引(Compound Index)
如果查询涉及多个字段,创建复合索引:
db.products.createIndex({ category: 1, price: -1 })
MongoDB 只能使用一个索引来优化查询,最好让索引的字段顺序匹配查询的使用方式。
③ 覆盖索引
如果 totalDocsExamined 仍然较大,可以使用覆盖索引来减少文档扫描:
db.products.find({ category: "Electronics" }, { category: 1, price: 1, _id: 0 }).explain("executionStats")
如果 "stage": "PROJECTION_COVERED",说明查询是覆盖索引,提高查询效率。
④ 使用 hint() 强制索引
如果 MongoDB 没有自动使用索引,可以用 hint() 手动指定:
db.products.find({ category: "Electronics" }).hint({ category: 1 })
4. 查询优化案例
案例 1:未使用索引
db.products.find({ category: "Electronics" }).explain("executionStats")
返回:
{
"queryPlanner": {
"winningPlan": { "stage": "COLLSCAN" }
},
"executionStats": {
"totalDocsExamined": 10000,
"executionTimeMillis": 50
}
}
优化方案:
db.products.createIndex({ category: 1 })
再次执行 explain(),查询优化成功:
{
"queryPlanner": {
"winningPlan": { "stage": "IXSCAN" }
},
"executionStats": {
"totalDocsExamined": 5,
"executionTimeMillis": 2
}
}
5. 总结
- 使用
explain("executionStats")分析查询计划,检查是否使用索引。 - 关注
stage是否是COLLSCAN,如果是,则需要优化索引。 - 通过
createIndex()创建索引,减少totalDocsExamined提高性能。 - 覆盖索引可以避免读取文档,减少查询时间。
- 使用
hint()强制使用特定索引,确保查询最优。
更多详细内容请关注其他相关文章!