使用构面的Mongodb聚合慢速计数

时间:2019-01-10 12:22:23

标签: mongodb aggregation-framework

我想使用一个构面来创建一个可用于获取分页数据的简单查询,但是我注意到,与仅运行两个单独的查询相比,如果执行此操作,我的性能将非常差。

作为一项快速测试,我创建了一个包含50000个随机文档的集合,并进行了以下测试。

var x = new Date();
var a = {
count : db.getCollection("test").find({}).count(),
data: db.getCollection("test").find({}).skip(0).limit(10)
};

var y = new Date();
print('result ' + a);
print(y - x);

var x = new Date();
var a = db.getCollection("test").aggregate(
    [
        { 
            "$match" : {

            }
        }, 
        {
         "$facet" : {
        "data": [
          {
            "$skip": 0
          },
          {
            "$limit": 10
          }
        ],
        "pageInfo": [
          {
            "$group": {
              "_id": null,
              "count": {
                "$sum": 1
              }
            }
          }
        ]       

         }
        }
    ]
)
var y = new Date();
print('result ' + a);
print(y - x);

其结果是,两个单独的查询一个用于查找另一个计数大约需要 2毫秒,而聚合单个查询最多需要 500毫秒

>

为什么聚合这么慢?

更新

即使是一个聚合中没有构面的计数也很慢

var x = new Date();
var a = db.getCollection("test").find({}).count();
var y = new Date();
print('result ' + a);
print(y - x);

var x = new Date();
var a = db.getCollection("test").aggregate(
    [
        { "$count" : "count" }
    ]
)
var y = new Date();
print('result ' + a);
print(y - x);

在上面带有我的测试数据集的情况下,聚合计数花费了 200ms ,而Count方法花费了 2ms

此问题扩展到NodeJs Mongodb驱动程序中,其中不赞成使用.Count()方法,并用countDocuments()方法代替。新的countDocuments()方法在后台使用聚合而不是count方法。发现就像我上面的示例一样,它的性能要差得多,以至于我将继续使用不推荐使用的方法,而不是使用较新的countDocuments()方法。

1 个答案:

答案 0 :(得分:0)

当然,这很慢。 count()方法仅在应用查询后返回游标的大小(不一定要读取所有文档,具体取决于您的查询和索引)。此外,对于空查询,查询优化器知道应返回所有文档,并且基本上只需要返回length(_id_1)

按照定义,聚合不能那样工作。除非有一个匹配阶段实际排除文档,否则每个文档都将从“磁盘” (目前MongoDB自己的缓存和FS缓存除外)中读取,以进行进一步处理。