索引
说明
索引可以高效执行的查询,如果没有索引.MongoDB必须执行集合扫描,即扫描集合中的每个文档.以选择与查询语句匹配的文档.如果查询存在适当的索引,MongoDB可以使用该索引限制它必须检查的文档数.索引是一种特殊的数据结构,它以易于遍历的形式存储集合数据集的一小部分.索引存储特定字段或字段集的值.按字段值排序.索引项的排序支持有效的相等匹配和基于范围的查询操作.此外,MongoDB还可以使用索引中的排序返回排序结果.
在创建集合的过程中,MongoDB在_id字段上创建一个唯一索引._id索引防止客户端为_id字段插入具有相同值的两个文档.
索引操作
创建索引
创建索引的语法为:db.collection.createIndex({<field>: <value>, ...},<options>).
- 当value为1时,索引按照正序排序
- 当value为-1时,索引按照倒叙排序
- options为创建索引时指定的参数
- { expireAfterSeconds: second}, 设置索引过期时间,单位秒
- { unique: true},创建唯一索引,索引字段的值不能重复
- { sparse: true},创建稀疏索引,把包含索引字段或字段为null的文档加入到索引中
- 唯一索引和稀疏索引可以同时具备,即索引字段必须唯一且可以为空
- 复合索引不具有过期时间的功能
# 为name字段创建正序索引
db.qvbilam.createIndex({ name: 1 })
# 返回
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1, # 创建索引前的索引数量
"numIndexesAfter" : 2, # 创建索引后的索引数量
"ok" : 1
}
当创建的索引为唯一索引时:索引字段缺少值的时候会设置为null,当插入的第二篇文档同样缺少索引字段的值是无法插入到集合中的.
查看索引
查看索引的语法.db.collection.getIndexes()
# 查看集合的索引
db.qvbilam.getIndexes()
# 返回
[
{ # 默认的_id索引
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{ # 新建的name索引
"v" : 2,
"key" : {
"name" : 1 # 按照姓名生序排序
},
"name" : "name_1" # 索引名称
}
]
删除索引
删除索引语法. db.collection.dropIndex('index_name')
# 删除name索引
db.qvbilam.dropIndex('name_1')
# 返回
{ "nIndexesWas" : 2, "ok" : 1 }
索引类型
# 文档数据
db.merchant.insertMany([
{ name: "Qvbilam", sex: 1, concat: {qq: 534511019, wx: "qvbilam", mobile: "135123"} },
{ name: "Eren", sex: 1, concat: {qq: 534511018, wx: "Eren", mobile: "1351234"} },
])
单健索引
MongoDB完全支持文档集合中任何字段的索引.默认情况下,所有集合都在_id字段上有一个索引.
嵌入字段创建索引
# 为concat中的qq字段创建升序索引
db.merchant.createIndex({ "concat.qq": 1 })
嵌入文档创建索引
# 为concat创建升序索引
db.merchant.createIndex({ concate: 1 })
复合索引
# 为concat创建复合索引,name与sex都是生序
db.merchant.createIndex({ name: 1, sex: 1 })
分析索引
验证索引是否被使用,db.collction.query().explain()
> db.qvbilam.find({ _id: "qvbilam_01" }).explain()
{
...
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN", # 阶段
"keyPattern" : {
"name" : 1
},
"indexName" : "name_1", # 使用的索引名称
...
"indexBounds" : {
"name" : [
"[\"qvbilam\", \"qvbilam\"]"
]
}
}
},
"rejectedPlans" : [ ]
},
}
对联合索引字段排序只有按照创建索引时设置的排序才有效.
值 | 说明 |
---|---|
COLLSCAN | 扫描全集合 |
IXSCAN | 扫描索引键中的数据 |
FETCH | 检索文件 |
SHARD_MERGE | 合并来自碎片的结果 |
SORT | 显式排序而不是使用索引顺序 |
嵌入文档
# 为嵌入文档创建索引
db.merchant.createIndex({ concat: 1 })
# 以下不支持索引
db.merchant.find({ "concat.qq": 534511019, "concat.wx": "qvbilam", "concat.mobile": "135123" })
联合索引
db.merchant.createIndex({ name: 1, sex: 1 })
# 当排序没有按照索引顺序排序 索引是无效的
db.merchant.find().sort({ name: 1,sex: -1 }).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "qvbilam.merchant",
"indexFilterSet" : false,
"parsedQuery" : {
},
"queryHash" : "0CC53D7A",
"planCacheKey" : "0CC53D7A",
"winningPlan" : {
"stage" : "SORT",
"sortPattern" : {
"name" : 1,
"sex" : -1
},
"memLimit" : 104857600,
"type" : "simple",
"inputStage" : {
"stage" : "COLLSCAN",
"direction" : "forward"
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "80e3cbe1e885",
"port" : 27017,
"version" : "4.4.0",
"gitVersion" : "563487e100c4215e2dce98d0af2a6a5a2d67c5cf"
},
"ok" : 1
}