目录
索引的概念
操作索引
#创建单键索引
删除索引
#创建复合索引
# 创建多键索引
# 唯一索引
# 索引的生存时间
索引效果解析
索引的概念
索引是特殊的数据结构,它以一种易于遍历的形式存储集合数据集的一小部分。索引存储一个或一组特定字段的值,按字段的值排序。
索引项的排序支持有效的相等匹配和基于范围的查询操作。此外,MongoDB可以通过使用索引中的排序返回排序后的结果。
mongo中使用 WiredTiger: B+
单键索引
如基于主键ID 进行的B+ tree 数据结构
复合索引(复合索引只能支持前缀子查询)
(A,B,C)
基于name, age, position 建立的复合索引
mongo默认id索引
在创建集合期间,MongoDB 在_id字段上创建唯一索引。该索引可防止客户端插入两个具有相同值的文档。你不能将_id字段上的index删除。
操作索引
# 准备数据
db.members.insertMany( [ {name:"zhangsan",age:19,tags:["00","It","SH"]}, {name:"lisi",age:35,tags:["80","It","BJ"]}, {name:"wangwu",age:31,tags:["90","It","SZ"]} ] );
#创建单键索引
db.members.createIndex({name:1})
# 索引的默认名称是索引键和索引中每个键的方向(即1或-1)的连接,使用下划线作为分隔符, 也可以通过指定 name 来自定义索引名称;
# db.members.createIndex({name:1},{ name: "whatever u like."});
# 查看索引
db.members.getIndexes()
# 对于单字段索引和排序操作,索引键的排序顺序(升序或降序)并不重要,因为MongoDB可以从任何方向遍历索引。
删除索引
# db.members.createIndex({name:-1},{ name:"index_self"});
# 删除
db.members.dropIndex("index_self")
#创建复合索引
MongoDB支持在多个字段上创建用户定义索引,即 复合索引。
复合索引中列出的字段的顺序具有重要意义。如果一个复合索引由 {name: 1, age: -1} 组成,索引首先按name 升序排序,然后在每个name值内按 age 降序 排序。
# 复合索引(名称+年龄)
db.members.createIndex({ name:1,age:-1});
对于复合索引和排序操作,索引键的排序顺序(升序或降序)可以决定索引是否支持排序操作。
# 创建多键索引
MongoDB使用多键索引来索引存储在数组中的内容。如果索引包含数组值的字段,MongoDB为数组的每个元素创建单独的索引项。数组字段中的每一个元素,都会在多键索引中创建一个键
db.members.createIndex( { tags:1});
# 唯一索引
db.members.createIndex({age:1},{unique:true});
db.members.find().pretty()
#新增重复数据报错
E11000 duplicate key error collection: test.members index: age_1 dup key: { age: 35.0 }
# 索引的稀疏性
索引的稀疏属性可确保索引仅包含具有索引字段的文档的条目。索引会跳过没有索引字段的文档。
可以将稀疏索引与唯一索引结合使用,以防止插入索引字段值重复的文档,并跳过索引缺少索引字段的文档。
db.sparsedemo.insertMany([{name:"xxx",age:19},{name:"zs",age:20}]);
db.sparsedemo.createIndex({name:1},{unique:true ,sparse:true});
可选字段 + 唯一约束:
最常用法。如用户表
null而冲突,加sparse: true即可让缺失字段的文档不参与唯一性校验。
# 索引的生存时间
在create_time创建,过期后,自动删除
db.members.createIndex({ create_time: 1},{expireAfterSeconds:30 });
索引效果解析
expelain(), 执行后关注winningPlan信息
可以使用 explain 进行分析的操作包含 aggregate, count, distinct, find ,group, remove, update winningPlan: stage 的值含义 COLLSCAN: 整个集合扫描 IXScan: 索引扫描 FETCH: 根据索引指向的文档的地址进行查询 SORT: 需要再内存中排序,效率不高#db.collection.explain().method({?});
db.members.explain().find({name:"xxx"});
#
只返回指定字段,效果更换
db.members.explain().find({name:"xxx"},{_id:0,name:1});
#删除索引后查看
# 出现了全扫描
#复合索引解析
db.members.explain().find().sort({"name":1,"age":-1})
db.members.explain().find().sort({"name":1,"age":1})
比较上面2个排序的差异