3
從mongodb集合中選擇隨機文檔的方法很多(如in this answer所述)。評論指出,在mongodb版本> = 3.2的情況下,在聚合框架中使用$sample
是首選。然而,在一個有許多小文件的收藏中,這似乎非常緩慢。
下面的代碼使用mongoengine來模擬這個問題,並把它比作「跳過隨機」方法:
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基本上是瞬時的。 – JohnnyHK
啊,3.2.0 - 那就是它。是的,[this](https://jira.mongodb.org/browse/SERVER-21887?jql=text%20~%20%22%24sample%22)表明這是一個已知的錯誤。 –
沒錯,但是我不確定爲什麼3.2.5版本中爲什麼它仍然很慢,因爲它在3.2.3中被標記爲固定。 – JohnnyHK