MongoDB中$in查询所传递参数的最大数量是多少? (Answer: MongoDB中$in查询所传递参数的最大数量没有硬性限制。)

82
在MongoDB中,$in查询所传递的最大参数数量是多少?

我在某个地方读到过,它是1,000,000。 - Roman
1
请查看下面显示计算过程的实际计算结果。 - Kevin J. Rice
4个回答

126

查询本身是一个文档。MongoDB将文档大小限制为16 MB(从版本2.4.0+开始)。

实际上,使用find进行的操作是:

db.collectionName.find(queryDoc)

'queryDoc' 是类似以下内容的东西:

{ 'fieldOne' : { $in : [ 1, 2, 3, 4] } }

要查找可以传递给$in查询的最大值,请使用bsonsize命令:

mongos> Object.bsonsize([1])
16
mongos> Object.bsonsize({ 'fieldOne' : { $in : [ 1, 2, 3, 4] } })
74
mongos> Object.bsonsize({ 'fieldOne' : { $in : [ 1, 2, 3, 4, 5] } })
85
mongos> Object.bsonsize({ 'fieldOne' : { $in : [ 1, 2, 3, 4, 5, 6] } })
96

因此,您可以看到每个额外的整数大小为11个字节。不是11位,而是11个字节。这是由于BSON在内部将数字至少存储为64位,再加上包装器所导致的。可以通过以下方式轻松查看:

mongos> Object.bsonsize({ 'fieldOne' : { $in : [ 1, 2, 3, 4, 5, 6, 69000] } })
107
mongos> Object.bsonsize({ 'fieldOne' : { $in : [ 1, 2, 3, 4, 5, 6, 6900000] } })
107
mongos> Object.bsonsize({ 'fieldOne' : { $in : [ 1, 2, 3, 4, 5, 6, 69000000000] } })
107
mongos> Object.bsonsize({ 'fieldOne' : { $in : [ 1, 2, 3, 4, 5, 6, 69000000000000] } })
107
mongos> Object.bsonsize({ 'fieldOne' : { $in : [ 1, 2, 3, 4, 5, 6, 6900000000000000] } })
107
mongos> Object.bsonsize({ 'fieldOne' : { $in : [ 1, 2, 3, 4, 5, 6, 690000000000000000] } })
107
mongos> Object.bsonsize({ 'fieldOne' : { $in : [ 1, 2, 3, 4, 5, 6, 69000000000000000000] } })
107
mongos> Object.bsonsize({ 'fieldOne' : { $in : [ 1, 2, 3, 4, 5, 6, 6900000000000000000000] } })
107
mongos> Object.bsonsize({ 'fieldOne' : { $in : [ 1, 2, 3, 4, 5, 6, 69000000000000000000000000] } })
107

因此,无论个别数字的大小如何,它们的bsonsize都是相同的。

现在来看问题本身:查询文档有多大?

将这些添加起来,对于一个具有$in子句的单字段查询,在pymongo、mongos javascript提示符中,不管怎样,所有的最大$in查询大小都会产生相同的加法事实:

mongos> Object.bsonsize({ 'a' : { '$in' : [1] }})
34
mongos> Object.bsonsize({ '' : { '$in' : [1] }})
33
mongos> Object.bsonsize({ '' : { '$in' : [] }})
22
  • 查询文档本身是22个字节;
  • 每个字段名称的每个字节添加一个字节;
  • 每个添加到$in子句的数字添加11个字节。

因此,假设您有一个一字节的字段名称(实际上是最小值),则您的最大值为:

mongos> 16*1024*1024
16777216
mongos> (16*1024*1024) - 22 - 1 
16777193
mongos> ((16*1024*1024) - 22 -1) / 11
1525199.3636363635

答案: 1,525,198(也就是1.5百万。这个数字很大啊。)


如果字段值不是一个数字,而是一个大小不同的字符串,你能帮忙处理吗? - Naseer Mohammad

36

看起来没有限制。

我进行了一个小测试。

1)集合A有-100万个简单的JSON对象{id:,name:}

2)在集合B中,我加载了集合A的引用ID,直到出现以下异常为止。我最多可以插入450k的引用计数。

Exception in thread "main" com.mongodb.MongoInternalException: DBObject of size 18388885 is over Max BSON size 16777216

3) 我可以将这些id作为 $in[id1...id450000] 发送,并从集合A中的100万个对象中获取整个450k id列表。

哇!这对我的应用程序来说已经足够多了 :D。MongoDB真的很酷。


7
我认为限制只取决于BSONDocument的大小。当您定义查询时,可以在$in子句中不断添加值,直到超过最大文档大小。因此,子句中可以包含多少个值取决于每个值有多大(每个值越小,就可以在$in子句中包含更多值)。
就性能而言,据我所知,在$in子句中的值的数量有一个“甜点”。请参见我在此相关问题中的答案:Is it OK to query a MongoDB multiple times per request?,即平衡$in子句中的值的数量与发送的查询次数。我正在撰写一篇博客文章来更详细地探讨这个问题。

0

我正在寻找一个答案来确认在IN子句中可以传递多少个UUID。所以,为了帮助其他人,我在这里发布结果。

我尝试像这样传递500个UUID:

 Object.bsonsize({ 'fieldOne' : { $in : [ 
    "3bd209e1-41c9-4ad2-a62c-bbe3d2ae490a",
    "3bd209e1-41c9-4ad2-a62c-bbe3d2ae490a",
    "3bd209e1-41c9-4ad2-a62c-bbe3d2ae490a".
     ..
     ..] } })

结果是:23518


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接