【问题标题】:Using an Index with Mongo's $first Group Operator将索引与 Mongo 的 $first 组运算符一起使用
【发布时间】:2020-04-22 16:11:32
【问题描述】:

根据Mongo最新的$group documentation,对$first有一个特别的优化:

优化返回每个组的第一个文档

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

这是有道理的,因为 $group 阶段中的每个 bin 只需要有序索引中的第一个条目。不幸的是,在我的测试中,我得到了一个查询,它在大约 1 秒内呈现约 800k 排序记录,然后将它们传递给 $group,其中大约需要 10 秒来呈现 key 的某些值的 1.7k 输出文档(参见下面的例子)。对于key 的其他值,超时时间为 300 秒。无论key 是什么,组中都应该正好有 1704 个 bin,并且这些查询 bin 应该被索引中的前三个条目覆盖,据我所知。我错过了什么吗?

db.getCollection('time_series').aggregate([
    {
        '$match': {
            'organization_id': 1,
            'key': 'waffle_count'
        }
    },
    {
        '$sort': {
            'key': 1, 'asset_id': 1, 'date_time': - 1
        }
    },
    {
        '$group': {
            '_id': {
                'key': '$key', 'asset_id': '$asset_id'
            },
            'value': {
                '$first': '$value'
            }
        }
    }
]);

这是索引:

{
    "organization_id": 1,
    "key": 1,
    "asset_id": 1,
    "date_time": -1
}

【问题讨论】:

  • .explain 说什么?这也取决于你是否有复合索引或单字段索引
  • 很难用可用信息分析您的查询。由于复合索引和索引前缀的性质,“优化以返回每个组的第一个文档”的示例可能不适用于您的情况。因此,即使是文档也表明,“可能是”(我自己的话)。但是,您可以单独尝试以下复合索引,并查看查询以及查询计划的结果是什么:@ 987654328@ { "key": 1, "asset_id": 1, "date_time": -1, "value": 1, "organization_id": 1 }.
  • @Ashh,.explain 是我如何知道通过排序的所有内容都在大约 1 秒内运行,从索引返回约 800k 排序条目,并且查询的其余部分在最佳情况下需要 10 秒。

标签: mongodb mongodb-query aggregation-framework query-optimization mongodb-indexes


【解决方案1】:

我向 Atlas 的 MongoDB 支持发送了一个请求。我引用的优化直到 4.2 版才可用(我们使用的是 3.6)。引用 Atlas 支持:

您提到的增强功能是在 4.2 中通过 SERVER-9507 实现的。对于您的特定示例,您似乎还需要实现SERVER-40090,以便您的管道充分利用改进。我们会让团队知道它对您的具体情况的潜在好处。

截至目前,第二个问题尚未解决,需要一个简单的 $group _id 设置,例如:

'_id': 'asset_id': '$asset_id'

而指定为对象的键将无法使用索引,即使它不是复合键,如下所示:

'_id': { 'asset_id': '$asset_id' }

【讨论】:

  • 感谢您让我们知道供应商支持人员告诉您的内容。
  • 快速更新 - 我们更新到 MongoDB 4.2 并且由于这种优化,速度提高了大约 10 倍,即使还没有第二次修复。
【解决方案2】:

我几乎遇到了类似的情况,我们有一个匹配、排序和分组的管道以相同的顺序。 虽然匹配和排序阶段能够使用索引组,但即使使用 4.2 也不使用索引。 即使在实现https://jira.mongodb.org/browse/SERVER-40090 之后,我也不认为它会允许在组 _id 上使用复合键。 例如

'_id': { 'asset_id': '$asset_id' }

^^ 将被支持

'_id': {'key': '$key', 'asset_id': '$asset_id'}

但是我认为 group 上的复合 _id 不能像上面的示例那样使用索引 ^^

【讨论】:

    猜你喜欢
    • 2018-10-23
    • 1970-01-01
    • 2015-01-01
    • 1970-01-01
    • 2020-04-22
    • 2017-11-17
    • 2013-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多