MongoDB 聚合 $sample 非常慢

Ste*_*ter 6 mongodb pymongo mongoengine

有很多方法可以从 mongodb 集合中选择随机文档(如本答案中所述)。评论指出,如果 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)))
Run Code Online (Sandbox Code Playgroud)

结果是:

Document 44551
agg took 21.89s
Document 25800
skip_random took 0.01s
Run Code Online (Sandbox Code Playgroud)

过去,无论我在 mongodb 遇到性能问题,我的答案始终是使用聚合框架,所以我很惊讶它的速度$sample如此之慢。

我在这里错过了什么吗?这个例子中是什么原因导致聚合花费了这么长时间?

Ste*_*ter 1

这是mongodb < 3.2.3 版本中 WiredTiger 引擎中已知错误造成的。升级到最新版本应该可以解决这个问题。

  • 我们使用的是 MongoDB 4.2.1 。$sample 仍然很慢。87K 尺寸,收藏 5 亿件。需要 20 分钟。服务器配置为 16c/240Gb (5认同)