我想使用一个构面来创建一个可用于获取分页数据的简单查询,但是我注意到,与仅运行两个单独的查询相比,如果执行此操作,我的性能将非常差。
作为一项快速测试,我创建了一个包含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()方法。
答案 0 :(得分:0)
当然,这很慢。 count()
方法仅在应用查询后返回游标的大小(不一定要读取所有文档,具体取决于您的查询和索引)。此外,对于空查询,查询优化器知道应返回所有文档,并且基本上只需要返回length(_id_1)
。
按照定义,聚合不能那样工作。除非有一个匹配阶段实际排除文档,否则每个文档都将从“磁盘” (目前MongoDB自己的缓存和FS缓存除外)中读取,以进行进一步处理。