【发布时间】:2017-03-21 22:52:13
【问题描述】:
我收集了大致如下结构的归档任务
{
"_id" : "job-id_00000001_2017-03-17T21:30:38.510Z",
"jobId" : "job-id",
"result" : {
"status" : "ok"
},
"..." : "..."
}
除此之外,我还有索引
jobId: 1
result.status: 1
jobId: 1, result.status: 1
在某些用例中,我需要相当频繁地更新统计信息(map: job-id -> status -> count)以及当我执行此聚合函数时...
db.getCollection('jobs_archive').aggregate([
{$group: {
_id: {jobId: "$jobId", status: "$result.status"},
count: { $sum: 1 }
}}
], {explain: true} )
...它在 120 万行上运行约 4 秒,而且这个时间长得令人无法接受。与explain: true 我得到...
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "db.jobs_archive",
"indexFilterSet" : false,
"parsedQuery" : {},
"winningPlan" : {
"stage" : "COLLSCAN",
"direction" : "forward"
},
"rejectedPlans" : []
}
...和 COLLSCAN 意味着 Mongo 不使用索引中的数据,但所有字段都在复合索引 jobId: 1, result.status: 1 中可用。
有没有办法优化aggregate 查询的性能?我做错了吗?
(由 Ori Dar 的回答触发的附录)
在深入研究文档后,我注意到“涵盖的查询”,在这种情况下应该使用我认为应该使用的功能。似乎不是。
涵盖的查询 https://docs.mongodb.com/manual/core/query-optimization/#covered-query
覆盖查询是可以完全使用 索引并且不必检查任何文档。一个索引涵盖一个 当以下两个都适用时查询:
- 查询中的所有字段都是索引的一部分,并且
- 结果中返回的所有字段都在同一个索引中。
...
由于索引包含查询所需的所有字段,MongoDB 既可以匹配查询条件,又可以仅使用返回结果 索引。
仅查询索引可以比查询文档快得多 指数之外。索引键通常小于 他们编目的文档,索引通常在 RAM 或 在磁盘上按顺序定位。
来自 Mongo 的更多怪异
(1) db.getCollection('jobs_archive').find({"jobId" : "job-id"}).count()
--> 0.375sec, count = 430000
(2) db.getCollection('archive').find({"jobId" : "job-id", "result.status": "ok"}).count()
--> 1.400sec, count = 430000
explain() 说
- winningPlan: IXSCAN / "indexName" : "jobId_1_result.status_1"
- 获胜计划:IXSCAN / "indexName" : "jobId_1"
所以,如果 Mongo 正确使用索引,我会为每个“job-id+status”组合使用“query().count()”(它是 6 * 5),但它似乎不在这个情况也是如此。当我指定两个键 'jobId + result.status' 复合索引不用于count() ...并且当我在查询中仅指定一个jobId 时,使用复合索引... r-r-r-r
注意:Mongo“版本”:“3.4.2”,Ubuntu 16
【问题讨论】:
标签: mongodb