MongoDB:比较两个大集合的最快方法
MongoDB: fastest way to compare two large sets
我有一个 Mongo 数据库集合,其中包含超过 2000 万个文档(并且还在快速增长)。有些文档有 'user_id'(其他文档没有)。
我经常需要检查集合中是否存在某些 user_id。但是有很多'some'。 10K 到 100K。
你会怎么做?
首先想到的是大查询:
$or : [ { 'user_id' : ... } , { ... } , ... ]
我有 10K 到 100K 个 ID...但是速度很慢,而且我认为这不是更好的方法。有人告诉我关于 Redis 的 bloom 过滤器,但似乎 Mongo 没有那样做。
您有更好的方法吗?与布隆过滤器一样,< 100% 的准确度在我的案例中是可以接受的。
您可以尝试使用 $in
进行集合比较:
db.users.find({ _id : { $in : [ 1, 2, 3, 4 ] } })
如果您在要搜索的字段上有索引,操作应该很快。如果您没有索引,并且预计需要经常重复该查询,那么您绝对应该构建一个。如评论中所述,如果 user_id 字段仅出现在某些文档中,则稀疏索引将适合您的集合。
我在 IPython 中对包含约 200M 文档的集合、在相对高规格笔记本电脑上的测试数据库进行了基准测试:
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
我有一个 Mongo 数据库集合,其中包含超过 2000 万个文档(并且还在快速增长)。有些文档有 'user_id'(其他文档没有)。
我经常需要检查集合中是否存在某些 user_id。但是有很多'some'。 10K 到 100K。
你会怎么做?
首先想到的是大查询:
$or : [ { 'user_id' : ... } , { ... } , ... ]
我有 10K 到 100K 个 ID...但是速度很慢,而且我认为这不是更好的方法。有人告诉我关于 Redis 的 bloom 过滤器,但似乎 Mongo 没有那样做。
您有更好的方法吗?与布隆过滤器一样,< 100% 的准确度在我的案例中是可以接受的。
您可以尝试使用 $in
进行集合比较:
db.users.find({ _id : { $in : [ 1, 2, 3, 4 ] } })
如果您在要搜索的字段上有索引,操作应该很快。如果您没有索引,并且预计需要经常重复该查询,那么您绝对应该构建一个。如评论中所述,如果 user_id 字段仅出现在某些文档中,则稀疏索引将适合您的集合。
我在 IPython 中对包含约 200M 文档的集合、在相对高规格笔记本电脑上的测试数据库进行了基准测试:
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