【发布时间】:2016-10-07 09:26:43
【问题描述】:
有很多方法可以从 mongodb 集合中选择随机文档(如 in this answer 所讨论的)。评论指出,如果 mongodb 版本 >= 3.2,那么在聚合框架中使用 $sample 是首选。但是,在包含许多小文档的集合上,这似乎非常慢。
以下代码使用 mongoengine 模拟问题,并与“skip random”方法进行比较:
import timeit
from random import randint
import mongoengine as mdb
mdb.connect("test-agg")
class ACollection(mdb.Document):
name = mdb.StringField(unique=True)
meta = {'indexes': ['name']}
ACollection.drop_collection()
ACollection.objects.insert([ACollection(name="Document {}".format(n)) for n in range(50000)])
def agg():
doc = list(ACollection.objects.aggregate({"$sample": {'size': 1}}))[0]
print(doc['name'])
def skip_random():
n = ACollection.objects.count()
doc = ACollection.objects.skip(randint(1, n)).limit(1)[0]
print(doc['name'])
if __name__ == '__main__':
print("agg took {:2.2f}s".format(timeit.timeit(agg, number=1)))
print("skip_random took {:2.2f}s".format(timeit.timeit(skip_random, number=1)))
结果是:
Document 44551
agg took 21.89s
Document 25800
skip_random took 0.01s
过去,无论我在哪里遇到 mongodb 的性能问题,我的答案一直是使用聚合框架,所以我很惊讶 $sample 这么慢。
我在这里遗漏了什么吗?是什么导致聚合需要这么长时间?
【问题讨论】:
-
您运行的是哪个 MongoDB 版本?我发现
$sample在3.2.5中很慢,但在3.2.7中基本是瞬时的。 -
啊,3.2.0 - 就是这样。是的,this 表明这是一个已知错误。
-
对,但我不知道为什么在 3.2.5 和 1M 文档的新集合中它仍然很慢,因为在 3.2.3 中标记为已修复。
标签: mongodb pymongo mongoengine