检索复合索引的一部分
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 毫秒)
我有一个大型集合,我想在其中检索按两个字段排序的结果。但是,我想开始以高效的方式从结果的深处检索结果。
例如,如果文件是:
{ 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 毫秒)