4 索引
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文档并选取那些符合查询条件的记录。
这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。
索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构
MongoDB中使用 B树
数据结构存储索引,B树在本次课程中不作讲解。
4.1 索引分类
4.1.1 单字段索引
MongoDB支持在文档单个字段上创建用户定义的升序/降序索引,称之为 单字段索引
4.1.2 复合索引
MongoDB还支持多个字段的索引,称之为 复合索引
复合索引中对字段顺序也有要求,如果复合索引是由 {age: 1, sex: -1} 组成,就会先按照age正序排序,再按照sex倒序排序
4.1.3 地理空间索引
为了支持对地理坐标的有效查询,MongoDB提供了二维索引和二维球面索引
4.1.4 文本索引
MongoDB提供了文本索引,支持在集合中搜索字符串内容。
4.1.5 哈希索引
为了支持散列的分片,MongoDB提供了散列索引,它对字段值的散列进行索引。哈希索引只支持 = 条件查询,不支持范围查询。
4.2 索引操作
4.2.1 创建索引
语法
db.集合.createIndex(keys, options)
参数 | 描述 |
---|---|
keys | 键值对,格式:{字段: 1或-1},如{age: 1}表示在age字段上的升序索引,-1则为降序索引 |
options | 可选参数,见下表 |
options配置
参数 | 描述 |
---|---|
background | 布尔类型,默认为false。指定是否后台创建索引。建索引的过程中会阻塞其它数据库操作,后台创建则可以避免这种问题 |
unique | 布尔类型,默认false。指定建立的索引是否唯一 |
name | 索引名称。MongoDB默认通过建立索引的字段名和排序顺序生成索引名称 |
示例
单字段索引:对 age
字段建立索引
db.user.createIndex({age: 1})
复合索引:对 age
和 sex
同时创建复合索引
db.user.createIndex({age: 1, sex: -1})
4.2.2 查看索引
返回一个集合中所有的索引
db.集合名.getIndexes()
其中,_id 是默认的索引。
MongoDB在创建集合的过程中,在_id字段上创建一个唯一的索引,名称为 _id_ ,该索引可以防止客户端插入两个具有相同值的文档,该索引不可以被删除。
查看看集合索引大小
db.集合名.totalIndexSize()
4.2.3 删除索引
删除指定索引
db.集合名.dropIndex(索引名称或索引键值对)
如删除age上的升序索引
db.user.dropIndex({age: 1})
或者
db.user.dropIndex("age_1")
删除所有索引
db.集合名.dropIndexes()
该方法并不会将_id索引删除,只能删除_id之外的索引
4.2.4 查询分析
MongoDB 查询分析可以确保我们所建立的索引是否有效。
查询分析常用的方法是 explain()
explain 操作提供了查询信息、使用索引、查询统计等,有利于我们对索引的优化。
先在user中创建age和sex索引
db.user.createIndex({age: 1, sex: 1})
再使用explain对查询进行分析
db.user.find({age: 18, sex: 1, _id: 1}).explain()
> db.user.find({age: 18, sex: 1}).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "bbs.user",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"age" : {
"$eq" : 18
}
},
{
"sex" : {
"$eq" : 1
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"age" : 1,
"sex" : -1
},
"indexName" : "age_1_sex_-1",
"isMultiKey" : false,
"multiKeyPaths" : {
"age" : [ ],
"sex" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"age" : [
"[18.0, 18.0]"
],
"sex" : [
"[1.0, 1.0]"
]
}
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "iZ2zebq96d1zohii1vadzqZ",
"port" : 27017,
"version" : "4.0.19",
"gitVersion" : "7e28f4296a04d858a2e3dd84a1e79c9ba59a9568"
},
"ok" : 1
}
重点看 stage
和 indexOnly
,这两个字段有时候可能并不会存在。
stage:当值为 COLLSCAN
时,表示全集合扫描,这样的性能是比较低的。当值为 IXSCAN
时,是基于索引扫描,创建索引后我们需要保证查询是基于索引扫描的
indexOnly:为true时表示使用到了索引
4.2.5 覆盖索引查询
覆盖索引查询和MySQL中的类似。当查询条件和所要查询的列全部都在索引中时,MongoDB会直接从索引返回结果。这样的查询性能非常的高