【问题标题】:Why $sort on indexed fields with $group stage does not exceed RAM limit, but $sort alone does?为什么在具有 $group 阶段的索引字段上的 $sort 不超过 RAM 限制,但单独使用 $sort 呢?
【发布时间】:2021-11-02 16:13:12
【问题描述】:

我有一个包含大约 50,000 个项目的集合,其中创建了索引,例如name_id

如果我使用db.items.find().sort({ name: 1, _id: 1 })

或:

db.items.aggregate([
    {
      $match: {}  
    },
    {
        $sort: {
            name 1,
            _id: 1
        }
    }
])

然后它超过了 RAM 限制:Executor error during find command :: caused by :: Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit.,如果我想让它工作,我必须通过 { allowDiskUse: true } 来聚合。

但是,当我在聚合管道中使用 $group 阶段时,它不会超过 RAM 限制并且可以正常工作:

db.items.aggregate.aggregate([
    {
      $match: {}  
    },
    {
        $sort: {
            name 1,
            _id: 1
        }
    },
    {
        $group: {
            _id: 1,
            x: {
                $push: {
                    _id: '$_id'
                }
            }
        }
    }
])

为什么仅$sort 会发生这种情况,而$sort + $group 不会发生这种情况?

【问题讨论】:

  • 您是否有两个独立的 name 和 id 索引或一个单一的 name 和 id 组合的复合索引(按此顺序)?
  • 我对名称和 ID 有单一索引,我不知道复合索引。现在我可以在不超过 RAM 限制的情况下进行查询。感谢您的帮助。

标签: mongodb aggregation-framework aggregate


【解决方案1】:

我有一个理论,它与this 功能有关。

如果管道按相同字段排序和分组,并且 $group 阶段仅使用 $first 累加器运算符,请考虑在与排序顺序匹配的分组字段上添加索引。在某些情况下,$group 阶段可以使用索引快速找到每个组的第一个文档。

虽然管道优化和“实际”运行的方式是一个黑匣子,但这是我唯一能想到的(至少在文档中提到)。

我假设这个“优化”开始了,使$group 阶段利用索引。这意味着管道可能在使用索引来扫描它时持有“较少”的内存。最终你不会返回 name 使总结果更小。

再次,这纯粹是猜测,但这是我得到的最好的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-29
    相关资源
    最近更新 更多