索引主要用于排序和检索。mysql里的索引存储结构是B+Tree,而mongo的索引结构是btree,两者的区别请查看我的另一篇博文《mysql5.7一颗B+树可以存放多少行数据?为什么使用B+树(B+Tree)而不是B树(BTree)?》
索引属性表
属性名 | 类型 | 说明 |
background | boolean | 是否后台构建索引,在生产环境中,如果数据量太大,构建索引可能会消耗很长时间,为了不影响业务,可以加上此参数,后台运行同时还会为其他读写操作让路 |
unique | boolean | 是否为唯一索引 |
name | string | 索引名字 |
sparse | boolean | 是否为稀疏索引,索引仅引用具有指定字段的文档。 |
创建索引
单键唯一索引:db.users.createIndex({username :1},{unique:true});
单键唯一稀疏索引:db.users. createIndex({username :1},{unique:true,sparse:true});
复合唯一稀疏索引:db.users. createIndex({username:1,age:-1},{unique:true,sparse:true}); // 按照username asc排序,按照age desc排序存储到索引,sparse true表示为稀疏索引,所谓稀疏索引,就是该文档有这个字段就为该文档建立索引,没有就不建。unique true表示唯一索引。
创建哈希索引并后台运行:db.users. createIndex({username :'hashed'},{background:true});
多键索引:在数组的属性上建立索引,例如:db.users. createIndex({favorites.city:1});针对这个数组的任意值的查询都会定位到这个文档,既多个索引入口或者键值引用同一个文档
删除索引
根据索引名字删除某一个指定索引:db.users.dropIndex("username_1");
删除某集合上所有索引:db.users.dropIndexs();
重建某集合上所有索引:db.users.reIndex();
查询集合上所有索引:db.users.getIndexes();
索引的特点
越多的索引代表占用内存越多,会让写入变慢。
mongoDB通常在一次查询里使用一个索引,所以多个字段的查询或者排序需要复合索引才能更加高效。
复合索引的顺序非常重要,参考MySQL里B+Tree索引的存储原理。
尽量在数据量变得庞大之前构建和优化索引,因为该过程往往开销很大,比如时间开销很大。
可以通过explain去验证查询中有没有用到索引,请查看《mongodb-4.4.10版本SQL查询进阶,mongodb与mysql的select SQL大比拼》
【复合索引使用案例分析】
mongo里的复合索引和mysql里的复合索引有着相似之处。假如建立了这样一个复合索引:
db.users. createIndex({username:1,age:-1}); 按照username升序age降序建立了一个索引
db.users.find({“username”:1,age:-1}).explain('executionStats') // 查询方式1,用到了索引
db.users.find({“username”:-1,age:1}).explain('executionStats') // 查询方式2,用到了索引
db.users.find({“username”:-1,age:-1}).explain('executionStats') // 查询方式3,没有用到索引,因为两个排序都没用上,参考mysql里的b+tree索引,它是不可以倒序去查询的
db.users.find({age:-1,“username”:1}).explain('executionStats') // 查询方式4,没有用到索引,因为字段顺序不对,参考mysql里的b+tree索引,字段查询顺序也很重要,不过这一点,mysql高版本里的查询优化器里有优化过
end.