0

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

{
    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 会将这些合并到一个阶段并决定在过滤之前对所有文档进行排序?
  • 我怎样才能防止这种情况?
4

2 回答 2

0

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

您可以强制使用以下索引$match

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

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

db.collection.createIndex({organization: 1, updated_on:1}, {background: true})
于 2019-12-14T08:38:34.220 回答
0

为什么 Mongo 会将这些合并到一个阶段并决定在过滤之前对所有文档进行排序?我怎样才能防止这种情况?

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

请参阅解释结果排序阶段


一些想法:

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

{ organization: 1, updated_on: 1 }

它会正常工作。请参阅有关索引的排序和非前缀子集的此主题。

(ii) 此外,find()查询可以做同样的工作,而不是聚合:

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

注意:请验证explain()并查看它们的执行情况。另外,尝试使用该executionStats模式。

于 2019-12-14T10:17:16.323 回答