【问题标题】:Overflow sort stage buffered data usage exceeds internal limit溢出排序阶段缓冲数据使用量超过内部限制
【发布时间】:2015-01-17 08:54:40
【问题描述】:

使用代码:

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 字节

我该如何处理?

【问题讨论】:

    标签: mongodb mongodb-query mongodb-indexes


    【解决方案1】:

    通过索引解决

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

    【讨论】:

    • 确保不要使用稀疏索引,如果您对每个文档进行排序,它们会被忽略
    • 对于 MongoDB 版本 >= 3,请使用:create_index 而不是 ensure_index,请参见此处:kb.objectrocket.com/mongo-db/…
    【解决方案2】:

    您的内存排序遇到了 32MB 的限制:

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

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

    【讨论】:

    • 最好声明一个索引,这样您就不需要在 RAM 中排序:更快、更可靠、有限的 RAM 使用量而不是潜在的无限量。如果您坚持,请将您的“查找”转换为聚合(可以使用 100MB 的 RAM 进行排序)并设置 allowDiskUse: true 以告诉聚合框架在超过 100MB 的 RAM 时溢出到磁盘。与仅声明适当的索引相比,预计会有严重的性能损失。 docs.mongodb.org/manual/reference/operator/aggregation/sort/…
    • 其实是可以改的。您需要运行此命令:db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes: <limit in bytes>})。来源:askubuntu.com/questions/501937/…
    • 请注意 mongoose 用户在你的模式中设置 index:true 将解决这个问题......猫鼬将检查你的所有模式并确保这些字段在开始之前实际上是索引应用程序...除非您使用 mySchema.set('autoIndex', false); 关闭此行为;
    • 我已经在排序字段上创建了一个索引,但它仍然给我这个“排序操作使用的 RAM 超过最大 33554432 字节”错误可能是因为我在排序之前应用了匹配操作并根据mongo doc 如果您在排序操作之前使用 match,它将忽略索引并在内存中对所有匹配的记录进行排序。
    • 如果这是公认的答案,那么它应该包含有关如何添加索引的信息。
    【解决方案3】:

    正如 kumar_harsh 在 cmets 部分所说,我想补充一点。

    您可以在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。 Rails 5/mongoid.yml ?
    • 我找到了。在我的终端上运行:mongod 并按照手册zocada.com/setting-mongodb-users-beginners-guide
    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

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

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

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

      【讨论】:

      • 在 pymongo 中是 db_handle.aggregate(pipe, allowDiskUse=True)。请参阅this question 了解更多信息!
      【解决方案6】:

      索引的 JavaScript API 语法:

      db_handle.ensureIndex({executedDate: 1})
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-02
        • 2017-03-23
        • 2016-01-15
        • 2015-08-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多