我收集了大致跟随结构的存档任务
{
"_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} )
...它在1.2ml行上运行~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()
说
所以,我会使用' query()。count()'对于每个工作ID +状态'的组合(如果是正确使用指数的话,是6 * 5),但是在这种情况下似乎也不是。当我指定两个键' jobId + result.status'复合索引不用于count()
...当我在查询中只指定一个jobId
时,使用复合索引... r-r-r-r
注意:Mongo"版本" :" 3.4.2",Ubuntu 16
答案 0 :(得分:0)
来自Pipeline Operators and Indexes
管道运算符和索引¶
$ match和$ sort管道运算符可以在管道开头出现时利用索引。
MongoDB 不会使用$group
在处理所有文档的意义上,您正在进行全面扫描。因此,使用索引会导致每个文档的重复查找:一次是索引,一次是文档本身,所以重点是什么。
因此,只有在首先使用$match
过滤器缩小结果范围时,才能使用索引。
作为旁注,{jobId: 1}
索引是多余的。
查询优化器可以使用{jobId: 1, result.status: 1}
索引使用以下模式进行查询:db.jobs_archive.find({jobId: n})
请参阅Prefixes