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)
。有关更多信息,请参阅!