溢出排序阶段缓冲的数据使用量超出内部限制


85

使用代码:

all_reviews = db_handle.find().sort('reviewDate', pymongo.ASCENDING)
print all_reviews.count()

print all_reviews[0]
print all_reviews[2000000]

计数打印2043484,然后打印all_reviews[0]

但是在打印时all_reviews[2000000],出现错误:

pymongo.errors.OperationFailure:数据库错误:运行程序错误:溢出排序阶段缓冲的33554495字节的数据使用量超过了33554432字节的内部限制

我该如何处理?

Answers:


118

您在内存中遇到了32MB的限制:

https://docs.mongodb.com/manual/reference/limits/#Sort-Operations

将索引添加到排序字段。这使MongoDB可以按排序顺序将文档流式传输给您,而不是尝试将它们全部加载到服务器上的内存中并在将它们发送到客户端之前对它们进行内存排序。


7
最好声明一个索引,这样您就不需要在RAM中排序:更快,更可靠,有限的RAM使用而不是无限的使用。如果您坚持认为,请将您的“查找”变成一个聚合(可以使用100MB的RAM进行排序),并设置allowDiskUse:true来告诉聚合框架在超过100MB的RAM时溢出到磁盘。与仅声明适当的索引相比,预期性能会受到严重影响。docs.mongodb.org/manual/reference/operator/aggregation/sort/...
A.杰西Jiryu戴维斯

31
实际上,可以更改它。您需要运行以下命令:db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes: <limit in bytes>})。来源:askubuntu.com/questions/501937/...
kumarharsh

6
对于猫鼬用户来说,要注意的是,在架构中的prop上设置index:true可以解决此问题...猫鼬将遍历所有架构,并确保在启动应用程序之前该字段实际上是索引...除非您可以使用mySchema.set('autoIndex',false)关闭此行为;
本杰明·科南

2
我在排序字段上创建了一个索引,但是仍然给我这个“排序操作使用的内存超过最大33554432字节”的错误,可能是因为我在排序之前应用了匹配操作,并且如果您在排序之前使用match的话,则根据mongo doc操作将忽略索引,并在内存中对所有匹配的记录进行排序。
Amol Suryawanshi

11
如果这是可接受的答案,那么它应该包括有关如何添加索引的信息。
菲利普·路德维希

45

kumar_harsh评论部分所述,我想补充一点。

您可以使用以下命令在admin数据库上查看当前缓冲区的使用情况:

> use admin
switched to db admin
> db.runCommand( { getParameter : 1, "internalQueryExecMaxBlockingSortBytes" : 1 } )
{ "internalQueryExecMaxBlockingSortBytes" : 33554432, "ok" : 1 }

它的默认值为32 MB(33554432字节)。在这种情况下,您的缓冲区数据不足,因此您可以使用自己定义的最佳值来增加缓冲区限制,例如50 MB,如下所示:

>  db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes:50151432})
{ "was" : 33554432, "ok" : 1 }

我们还可以通过mongodb配置文件中的以下参数永久设置此限制:

setParameter=internalQueryExecMaxBlockingSortBytes=309715200

希望这可以帮助 !!!

Note:此命令仅在3.0 +版本之后才支持


在配置文件中永久设置此限制的方法是什么?我有一台专用于mongo的1 TB内存计算机,我希望将其永久启动。
萨曼莎·阿特金斯

@SamanthaAtkins我已经更新了答案,可以在配置文件中永久设置它。
杰瑞

@JERRY在哪里永久设置在轨道上。Rails 5 / mongoid.yml吗?
Prateep Kul

我找到了。在我的终端上运行:mongod,并遵循手册zocada.com/setting-mongodb-users-beginners-guide
Prateep Kul

24

用索引解决

db_handle.ensure_index([("reviewDate", pymongo.ASCENDING)])

确保不要使用稀疏索引,如果对每个文档进行排序,它们都会被忽略
Charly Koza

15

如果要避免创建索引(例如,您只想进行快速检查以浏览数据),则可以将聚合与磁盘使用情况结合使用:

all_reviews = db_handle.aggregate([{$sort: {'reviewDate': 1}}], {allowDiskUse: true})

(不过,不确定如何在pymongo中执行此操作)。


在pymongo中是db_handle.aggregate(pipe, allowDiskUse=True)。有关更多信息,请参见此问题
Genarito

3

索引的JavaScript API语法:

db_handle.ensureIndex({executedDate: 1})

2

就我而言,有必要在代码中修复必要的索引并重新创建它们:

rake db:mongoid:create_indexes RAILS_ENV=production

因为当需要字段索引时不会发生内存溢出。

PS在此之前,我必须禁用创建长索引时的错误:

# mongo
MongoDB shell version: 2.6.12
connecting to: test
> db.getSiblingDB('admin').runCommand( { setParameter: 1, failIndexKeyTooLong: false } )

也可能需要reIndex

# mongo
MongoDB shell version: 2.6.12
connecting to: test
> use your_db
switched to db your_db
> db.getCollectionNames().forEach( function(collection){ db[collection].reIndex() } )
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.