500万mongo doc:
{
_id: xxx,
devID: 123,
logLevel: 5,
logTime: 1468464358697
}
索引: DEVID
我的聚合:
[
{$match: {devID: 123}},
{$group: {_id: {level: "$logLevel"}, count: {$sum: 1}}}
]
汇总结果:
{ "_id" : { "level" : 5 }, "count" : 5175872 }
{ "_id" : { "level" : 1 }, "count" : 200000 }
汇总解释:
numYields:42305
29399ms
问: 如果mongo没有写入(保存)数据,则需要29秒 如果mongo正在写(保存)数据,则需要2分钟 我的汇总结果需要回复网页,所以29秒或2分钟太长了 我怎么解决呢?优选10秒或更短 谢谢大家
答案 0 :(得分:0)
在您的示例中,{devID: 123, logLevel:5}
的聚合查询返回5,175,872的计数,看起来它计算了集合中的所有文档(因为您提到了您有500万个文档)。
在这个特定的例子中,我猜测{$match: {devID: 123}}
阶段几乎匹配每个文档,因此聚合正在进行基本上是一个集合扫描。根据您的RAM大小,这可能会导致您的工作集推出内存,并减慢服务器正在执行的每个其他查询的速度。
如果您无法为$match
阶段提供更具选择性的标准(例如,使用一系列logTime
以及devID
),那么预先汇总的报告可能是您的最佳选择。
一般而言,预聚合报告是包含所需聚合信息的文档,每次插入相关集合时都会更新此文档。例如,您可以在单独的集合中包含单个文档,如下所示:
{log:
{devID: 123,
levelCount: [
{level: 5, count: 5175872},
{level: 1, count: 200000}
]
}}
每次插入日志集时,都会使用相关详细信息更新该文档。
使用预先聚合的报告,您不再需要运行聚合查询。相反,您可以使用单个find()
查询来获取所需的汇总信息。
有关预先汇总报告的更多示例,请参阅https://docs.mongodb.com/ecosystem/use-cases/pre-aggregated-reports/