【问题标题】:mongo sort before match in aggregation聚合中匹配前的mongodb排序
【发布时间】:2019-12-14 07:39:03
【问题描述】:

给定一个包含几百万个文档的集合,如下所示:

{
    organization: ObjectId("6a55b2f1aae2fe0ddd525828"),
    updated_on: 2019-04-18 14:08:48.781Z
}

和 2 个索引,在两个键 {organization: 1} 和 {updated_on: 1}

以下查询需要很长时间才能返回:

db.getCollection('sessions').aggregate([
        {
                "$match" : {
                        "organization" : ObjectId("5a55b2f1aae2fe0ddd525827"),
                }
        },
        {
                "$sort" : {
                        "updated_on" : 1
                }
        }
])

需要注意的是,结果是 0 个匹配项。经过进一步调查,explain() 中的规划器实际上返回以下内容:

{
    "stage" : "FETCH",
    "filter" : {
        "organization" : {
            "$eq" : ObjectId("5a55b2f1aae2fe0ddd525827")
        }
    },
    "inputStage" : {
        "stage" : "IXSCAN",
        "keyPattern" : {
            "updated_on" : 1.0
        },
        "indexName" : "updated_on_1",
        "isMultiKey" : false,
        "multiKeyPaths" : {
            "updated_on" : []
        },
        "isUnique" : false,
        "isSparse" : false,
        "isPartial" : false,
        "indexVersion" : 2,
        "direction" : "forward",
        "indexBounds" : {
            "updated_on" : [ 
                "[MinKey, MaxKey]"
            ]
        }
    }
}
  • 为什么 Mongo 会将这些合并到一个阶段并决定在过滤之前对所有文档进行排序?
  • 如何防止这种情况发生?

【问题讨论】:

标签: mongodb aggregation-framework query-planner


【解决方案1】:

为什么 Mongo 会将这些合并为一个阶段并决定对所有 过滤前的文件?我怎样才能防止这种情况发生?

排序确实发生在比赛阶段之后。查询计划显示 SORT 阶段 - 这是因为排序键 updated_on 上有一个索引。如果您删除 updated_on 字段上的索引,您在查询计划中看到一个 SORT 阶段(它将是内存中的排序)。

Explain Results - sort stage


一些想法:

(i) 您可以使用复合索引,而不是两个单字段索引:

{ organization: 1, updated_on: 1 }

它会正常工作的。请参阅Sort and Non-prefix Subset of an Index 上的此主题。

(ii) 此外,find() 查询可以代替聚合来完成相同的工作:

db.test.find( { organization : ObjectId("5a55b2f1aae2fe0ddd525827") } ).sort( { updated_on: 1 } )

注意:一定要通过explain() 进行验证,看看他们的表现如何。另外,请尝试使用executionStats 模式。

【讨论】:

    【解决方案2】:

    MongoDB 将使用$sort 上的索引,因为这是一项繁重的操作,即使之前匹配会限制要排序的结果,

    您可以强制使用$match 的索引:

    db.collection.aggregate(pipeline, {hint: "index_name"})
    

    或者创建一个更好的索引来解决这两个问题,查看更多信息here

    db.collection.createIndex({organization: 1, updated_on:1}, {background: true})
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-16
      • 1970-01-01
      • 2020-06-29
      • 2019-01-24
      • 1970-01-01
      • 2019-07-17
      相关资源
      最近更新 更多