了解性能:mongo聚合与计数

时间:2014-02-21 06:33:13

标签: mongodb mongodb-query aggregation-framework nosql

如果我进行计数查询,我会在< 2seconds

中得到结果
db.coll.find({"A":1,"createDate":{"$gt":new Date("2011-05-21"),"$lt":new Date("2013-08-21")}}).count()

这使用以下索引

db.coll.ensureIndex({"A":1,"createDate":1})

类似地,有4列A,B,C,D(值总是0或1),我运行4个计数查询并得到< 10seconds的结果。

我查看了聚合框架文档并创建了一个聚合查询来一起完成所有4个总和。

db.coll.aggregate(  { $match : {"createDate":{$gt:new Date("2013-05-21"),$lt:new Date("2013-08-21")} } },
{ $group :
                         { _id:null,
                         totalA : { $sum : "$A" },
                         totalB : {$sum: "$B},
                         totalC:{$sum: "$C"},
                         totalD:{$sum: "$D"}}} 
 ) 

我还创建了一个索引:

db.coll..ensureIndex({"createDate":1,"A":1,"B":1,"C":1,"D":1})

根据文档,该索引涵盖了我的聚合函数。但聚合的返回时间约为18秒。

我在这里很困惑。有没有什么基本的我错过或有任何基本概念落后,这使得聚合慢于计数。 我还担心由于从获取计数的代码中从mongo触发的查询数量而导致的开销。

2 个答案:

答案 0 :(得分:7)

首先,虽然没有记录2.4.8,但您可以使用db.runCommand调用运行解释:

db.runCommand({
    aggregate: "coll",
    pipeline: [      
        { $match : 
            {"createDate":{$gt:new Date("2013-05-21"),$lt:new Date("2013-08-21")} } 
        },
        { $group : { 
              _id:null,
              totalA: {$sum :"$A"},
              totalB: {$sum: "$B"},
              totalC: {$sum: "$C"},
              totalD: {$sum: "$D"}
        }} 
    ],
    explain: true
})

这会让您对正在发生的事情有所了解。

此外,您主要是将 apple oranges 进行比较。

当您在查询上发出count()时,它使用游标结果属性来获取匹配的文档数。

在聚合下,您正在选择扩展匹配,然后将所有这些结果压缩为所有项目的总和。如果您的初始$匹配结果很多,那么所有这些都需要与$ sum一起进行。

看看解释,并尝试从概念上理解差异。聚合非常适合您通常希望它做的事情。但也许这不是最好的用例。

答案 1 :(得分:4)

简短回答:在你的情况下,聚合速度较慢,因为它涉及更多数据处理,而使用索引mongo可以有效地计算计数。聚合用于计算一些复杂的结果(grouping等),而简单计算count()就足够了。

原因是mongodb中的聚合是一个聚合数据的框架,它基于数据处理流水线的概念。 Mongo逻辑上将整个集合传递到聚合管道。这就是整个聚合没有explain的原因(截至本文时,版本2.4)。这意味着基本上有一种访问方法,其余的时间用于处理。但似乎支持explain in recent versions.

您可以对使用集合中的数据子集进行早期过滤。

  
    

早期过滤

         

如果您的聚合操作只需要a中的一部分数据     集合,使用$match$limit$skip阶段来限制     在管道开头输入的文档。当放置在     在管道的开头,$ match操作使用合适的索引     仅扫描集合中的匹配文档。

         

放置$ match管道阶段,然后在开始时放置$sort阶段     管道在逻辑上等同于具有排序的单个查询     并且可以使用索引。如果可能,将$ match运算符放在     管道的开始。

  

Aggregation pipeline behaviour.

相关问题