检索复合索引的一部分

Retrieving a section of a compound index

我有一个大型集合,我想在其中检索按两个字段排序的结果。但是,我想开始以高效的方式从结果的深处检索结果。

例如,如果文件是:

{ age: 25, name: "Gabe" }
{ age: 25, name: "John" }
{ age: 25, name: "Mike" }
{ age: 26, name: "Gabe" }
{ age: 26, name: "John" }
{ age: 26, name: "Mike" }

我想检索按{年龄:1,姓名:1}排序的文件。我想直接索引到 { age: 26, name: "John" } 并按照复合索引的顺序检索下 N 个文档(例如 { age: 26, name: "Mike" })。目的是 return 将搜索结果分页给用户。

这正是 mongodb 索引查询的工作方式。

MongoDB 索引类似于 b-tree 结构。当复合索引用于选择和排序时,查询执行器将从第一个匹配值开始扫描索引,并扫描最后一个匹配值。然后提取识别出的文档以传递到任何进一步的查询阶段。

一些查询可能需要扫描索引的多个范围。示例查询,扫描索引的单个范围将按顺序找到所有匹配的文档,因此不需要额外排序。

此查询需要两部分,一部分匹配第一个年龄和部分姓名列表,另一部分匹配其余年龄。这可以通过 $or 运算符来完成。

为了演示这一点,我使用了 explain 和 executionStats 选项:

db.collection.explain("executionStats").find({$or:[{age:{$eq:25},name:{$gte:"John"}},{age:{$gt:25}}]}).sort({age:1,name:1})

获胜的计划显示了两个索引扫描,将它们的结果传递到合并阶段。注意 fetch 阶段没有注意到任何进一步的过滤,也没有 in-memory sort:

"winningPlan" : {
            "stage" : "SUBPLAN",
            "inputStage" : {
                "stage" : "FETCH",
                "inputStage" : {
                    "stage" : "SORT_MERGE",
                    "sortPattern" : {
                        "age" : 1,
                        "name" : 1
                    },
                    "inputStages" : [
                        {
                            "stage" : "IXSCAN",
                            "keyPattern" : {
                                "age" : 1,
                                "name" : 1
                            },
                            "indexName" : "age_1_name_1",
                            "isMultiKey" : false,
                            "multiKeyPaths" : {
                                "age" : [ ],
                                "name" : [ ]
                            },
                            "isUnique" : false,
                            "isSparse" : false,
                            "isPartial" : false,
                            "indexVersion" : 2,
                            "direction" : "forward",
                            "indexBounds" : {
                                "age" : [
                                    "[25.0, 25.0]"
                                ],
                                "name" : [
                                    "[\"John\", {})"
                                ]
                            }
                        },
                        {
                            "stage" : "IXSCAN",
                            "keyPattern" : {
                                "age" : 1,
                                "name" : 1
                            },
                            "indexName" : "age_1_name_1",
                            "isMultiKey" : false,
                            "multiKeyPaths" : {
                                "age" : [ ],
                                "name" : [ ]
                            },
                            "isUnique" : false,
                            "isSparse" : false,
                            "isPartial" : false,
                            "indexVersion" : 2,
                            "direction" : "forward",
                            "indexBounds" : {
                                "age" : [
                                    "(25.0, inf.0]"
                                ],
                                "name" : [
                                    "[MinKey, MaxKey]"
                                ]
                            }
                        }
                    ]
                }
            }
        },

executionStats 部分显示查询执行器检查了 2 个索引键和 2 个文档,从该查询返回的文档总数为 2:

    "executionStats" : {
        "executionSuccess" : true,
        "nReturned" : 5,
        "executionTimeMillis" : 3,
        "totalKeysExamined" : 5,
        "totalDocsExamined" : 5,

(我的笔记本电脑有点动力不足,所以实际上该查询需要 3 毫秒)