【问题标题】:MongoDB: fastest way to compare two large setsMongoDB:比较两个大集合的最快方法
【发布时间】:2015-05-08 10:31:50
【问题描述】:

我有一个 MongoDB 集合,其中包含超过 2000 万个文档(并且还在快速增长)。有些文档有一个“user_id”(其他文档没有)。

我经常需要检查集合中是否存在一些 user_id。但是有很多“一些”。 10K 到 100K。

你会怎么做?

第一个念头就是来个大查询:

$or : [ { 'user_id' : ... } , { ... } , ... ]

使用我所有的 10K 到 100K id...但是它非常慢,我认为这不是更好的方法。有人告诉我 Redis 的布隆过滤器,但似乎 Mongo 没有这样做。

您有更好的方法吗?与布隆过滤器一样,在我的情况下,

【问题讨论】:

  • 如果您使用聚合框架,MongoDB 支持使用 $match 进行过滤。您可能想要使用sparse 索引。
  • 如果我理解得很好,问题是“如何编写查询来查找大量值与集合中的值集之间的交集”。关键是如何传递要比较的“大量”值。
  • 不知何故相关:查询大小显然有 16MB 的限制 -- stackoverflow.com/questions/11688658/…
  • 您可以随时部署自己的布隆过滤器。只要您不删除文档。
  • (该死的 5 分钟限制)尽管请记住,这不是灵丹妙药。您将过滤掉不在数据库中的用户,但您仍然需要查询那些通过过滤器的用户。

标签: mongodb bloom-filter large-data


【解决方案1】:

您可以尝试使用$in 进行设置比较:

db.users.find({ _id : { $in : [ 1, 2, 3, 4 ] } })

如果您正在搜索的字段上有索引,则操作应该很快。如果您没有索引,并且您预计需要经常重复该查询,那么您绝对应该构建一个。如 cmets 中所述,如果 user_id 字段仅存在于某些文档中,则稀疏索引将适合您的集合。

我在 IPython 中对包含约 2 亿个文档的集合进行了基准测试,该集合是在相对较高规格的笔记本电脑上的测试数据库上进行的:

import random
from pymongo import MongoClient

client = MongoClient()
db = client["anonymised"]

# generate 100K random ids for testing purposes
ids = [ random.randint(0, int(1e6)) for i in range 100000 ]

%time db.users.count({ "_id" : { "$in" : ids } })
CPU times: user 182 ms, sys: 75.5 ms, total: 257 ms
Wall time: 16.1 s
# returns 32631

如果您想对此进行改进,则必须考虑对数据库进行分片,以便在活动内存中保留更重要的部分。在整个工作集都在内存中的生产环境中,此操作可能会明显更快。

相比之下,您最初采用的“$or”方法:

query = [ { "_id" : v } for v in ids ]

%time db.users.count({ "$or" : query })
CPU times: user 1.4 s, sys: 682 ms, total: 2.08 s
Wall time: 35min 30s

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-18
    • 2015-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多