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

Mongodb 溢出排序阶段缓冲数据使用超过内部限制,mongodb,mongodb-query,mongodb-indexes,Mongodb,Mongodb Query,Mongodb Indexes,使用代码: all_reviews = db_handle.find().sort('reviewDate', pymongo.ASCENDING) print all_reviews.count() print all_reviews[0] print all_reviews[2000000] 计数打印2043484,并打印所有审查[0] 但是,当打印所有的\u评论[2000000]时,我得到了一个错误: pymongo.errors.OperationFailure:数据库错误:运行程序

使用代码:

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

print all_reviews[0]
print all_reviews[2000000]
计数打印
2043484
,并打印
所有审查[0]

但是,当打印
所有的\u评论[2000000]
时,我得到了一个错误:

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

如何处理此问题?

通过索引解决

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

内存中的排序将达到32MB的限制:


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

正如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
希望这有帮助


注意
:此命令仅在版本3.0+后支持

在我的情况下,有必要修复代码中的多余索引并重新创建它们:

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 } )
也可能需要重新编制索引:

# 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() } )

如果您希望避免创建索引(例如,您只需要快速而不干净的检查来浏览数据),您可以使用磁盘使用率的聚合:

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

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

索引的JavaScript API语法:

db_handle.ensureIndex({executedDate: 1})

最好声明一个索引,这样就不需要在RAM中进行排序:更快、更可靠、有限的RAM使用,而不是潜在的无限使用。如果您坚持,请将“find”转换为聚合(可以使用100MB的RAM进行排序),并将allowDiskUse:true设置为告诉聚合框架在超过100MB的RAM时溢出到磁盘。与仅仅声明一个适当的索引相比,可能会受到严重的性能损失。事实上,它是可以改变的。您需要运行以下命令:
db.adminCommand({setParameter:1,internalQueryExecMaxBlockingSortBytes:})
。来源:值得注意的是,对于mongoose用户,在模式中的道具上设置index:true将解决此问题。。。mongoose将检查您的所有模式,并确保在启动应用程序之前字段实际上是索引。。。除非使用mySchema.set('autoIndex',false)关闭此行为;我已经在排序字段上创建了一个索引,但它仍然给了我这个“排序操作使用了超过最大33554432字节的RAM”错误可能是因为我在排序之前应用了匹配操作,并且根据mongo文档,如果在排序操作之前使用匹配操作,它将忽略索引,并对所有匹配的记录执行内存内排序。如果这是可接受的答案,则应包括有关如何添加索引的信息。请确保不要使用稀疏索引,如果您对MongoDB版本>=3的每个文档进行排序,则会忽略它们使用:
create_index
而不是
sure_index
请参见此处:如何在配置文件中永久设置此限制?我有一台1 TB内存机器专用于mongo,我想永久启动它。@SamanthaAtkins我已经更新了答案,以便在配置文件中永久设置它。@JERRY,在rails中永久设置在何处。Rails 5/mongoid.yml?我找到了。使用:mongod在我的终端上运行,并遵循pymongo中的手册将是
db\u handle.aggregate(pipe,allowDiskUse=True)
。有关更多信息,请参阅!