数据库索引与书籍的索引类似。有了索引就不需要反正本书,数据库可以直接在索引中查找。在索引中找到条目后就可以直接跳转到目标文件中,这能使查找速度提高几个数量级。
复合索引
1.建立
db.user.ensureIndex({“age”:1,”username”:1});
每一个索引条目都包含一个“age”字段和一个“username”字段,并且指向文档在磁盘上的存储位置(重点)。
2.使用
mongodb对这个索引的使用方式取决于查询的类型。下面是三种主要的方式。
db.users.find({“age”:21}).sort({“username”:-1})
//点查询 索引中第二个字段是有序的,可以逆序遍历索引而不用在内存中排序
//排序方向并不重要:mongodb可以在任意方向上对索引进行遍历db.users.find({“age”:{“ gte":21," lte”:30}})
//多值查询,范围查询。会使用索引的第一个字段。按照索引顺序排列的。db.users.find({“age”:{“ gte":21," lte”:30}}).sort({“username”:1})
//本次查询可以用到上索引的第一个字段,但需要在内存中排序,所以施非高效的。
可以使用这个索引。可以通过hint指定查询所需要的索引。
db.user.ensureIndex({“username”:1”,”age”:1});
若对查询结果的范围做了限制,那么mongodb在几次匹配之后就可以不再扫描索引。
//对于这句话,我个人认为第二种索引目的文档是在一起的,当找到第一部分后,可以继续读取下面的文档,而不必再去遍历整个索引来查找。
在这种情况下,将排序见放在第一位是一个非常好的策略。
在一般的小型集合中第一种占优,但不利于扩展,所以当集合足够到时,建议创建常用排序键在前的索引,这样的索引更利于扩展。
//这样的索引树被称为右平衡索引。
3.索引数组和内嵌文档
索引内嵌文档。
db.users.ensureIndex({“loc”:1})
索引内嵌文档的字段,要用到点语法。
db.users.ensureIndex({“loc.city”:1})
对嵌套文档本身建立索引和对嵌套文档的某个字段建立索引是不同的。
只有在与子文档字段顺序完全匹配的子文档查询时,才会应用到。
索引数组,可以高效的搜索数组中的特定元素。
db.users.ensureIndex({“comments.date”:1})
注意mongodb的数组索引在同一个索引中不能大于一,也就是说每个索引做多包含一个数组索引,以防索引爆炸性增长。
索引基数指的是某个键所对应不同值得数量。基数越高,这个键上的索引越有效,应高尽量将基数高的索引放在复合索引的前面。
注意:数组索引被标记为多键索引,指向的文档很大可能会重复(将这个键设置为复合唯一索引自动去重),所以必须要去重。更改的方式为删除新建,不能直接更改。
4.索引种类
唯一索引
创建:
db.users.ensureIndex({“username”:1},{“unique”:true});
当创建唯一索引时,有可能失败的原因大概是因为已经存在重复的值。
在极少情况下,可能希望直接删除重复的值。创建索引时使用”dropDups“
选项,当遇到重复的值时,保留第一个,删除剩下的重复文档。
db.users.ensureIndex({“username”:1},{“unique”:true,”dropDups”:true});
稀疏索引
唯一索引会把null看做值,所以无法将多个缺少唯一索引中的键的文档插入到集合中。然而,在有些情况下,你可能希望唯一索引只对包含相应的文档生效。如果有一个可能存在可能不存在的字段(例如唯一的绑定邮箱或者手机等等),但是当他存在时必须是唯一的,可以讲unique和sparse选项组合起来使用。
db.users.ensureIndex({“username”:1},{“unique”:true,”sparse”:true})
5.索引管理
可以在system.indexes中看到它的元信息,可以执行db.collectionName.getIndexes()来查看给定集合上的所有索引信息。
6.标识索引
db.users.ensureIndex({“username”:1},{“name”:”username”})
7.修改索引
db.users.dropIndex(“username”)
用索引描述信息中的name字段来指定需要删除的索引。