介绍
首先,覆盖索引并不是一种索引,而是指一种查询优化的行为。
我们知道,在一棵二级索引的B+树上,索引1的值存在于树的叶子节点上。因此,如果我们希望查询的字段被包含在索引中,则直接查找二级索引树就可以获得,而不需要再次通过_id索引查找出原始的文档。
相比“非覆盖式”的查找,覆盖索引1的这种行为可以減少一次对最终文档数据的检索操作(该操作也被称为回表)。
大部分情况下,二级素引树常驻在内存中,覆盖索引式的查询可以保证一次检索行为仅仅发生在内存中,即避免了对磁盘的1/0操作,这对于性能的提升有显著的效果。
简单来说,就是需要查询的字段已经在索引里了,可以优化查询的方式,使mongo不去查源文档,从而减少一次查询
怎么用
假设doc结构如下:
{
"_id" : ObjectId("62764716ecf253c7e26f4af3"),
"name" : "1",
"gender" : "male"
}
现有索引:
db.user.ensureIndex({name: 1})
按下面方式查询时会触发覆盖索引优化:
db.user.find({name: "1"}, {name: 1, _id: 0})
_id: 0
让_id字段不要随查询返回
使用下面命令确认:
db.user.find({name: "1"}, {name: 1, _id: 0}).explain()
/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test01.user",
"indexFilterSet" : false,
"parsedQuery" : {
"name" : {
"$eq" : "1"
}
},
"queryHash" : "3066FB64",
"planCacheKey" : "A5386A93",
"winningPlan" : {
"stage" : "PROJECTION_COVERED",
"transformBy" : {
"name" : 1.0,
"_id" : 0.0
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"name" : 1.0
},
"indexName" : "name_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"name" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"name" : [
"[\"1\", \"1\"]"
]
}
}
},
"rejectedPlans" : []
},
"serverInfo" : {
"host" : "dev03-ufile-69-21",
"port" : 28018,
"version" : "4.4.2-2-g200cba6",
"gitVersion" : "200cba613b10a2edb9ced9def5c4a2000062330f"
},
"ok" : 1.0
}
对比不加_id: 0
/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test01.user",
"indexFilterSet" : false,
"parsedQuery" : {
"name" : {
"$eq" : "1"
}
},
"queryHash" : "D8E51AF6",
"planCacheKey" : "1A14F94A",
"winningPlan" : {
"stage" : "PROJECTION_SIMPLE",
"transformBy" : {
"name" : 1.0
},
"inputStage" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"name" : 1.0
},
"indexName" : "name_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"name" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"name" : [
"[\"1\", \"1\"]"
]
}
}
}
},
"rejectedPlans" : []
},
"serverInfo" : {
"host" : "dev03-ufile-69-21",
"port" : 28018,
"version" : "4.4.2-2-g200cba6",
"gitVersion" : "200cba613b10a2edb9ced9def5c4a2000062330f"
},
"ok" : 1.0
}
- IXSCAN, 索引扫描阶段
- PROJECTION,投射阶段,即提取对应的name字段
- FETCH,文档获取阶段