第五章 索引¶
- 索引可以用来优化查询,而且在某些特定类型的查询中,索引是必不可少的。
- 什么是索引,为什么要用索引。
- 如果选择需要建立索引的字段
- 如何强制使用索引,如果评估索引的效率
- 创建索引和删除索引
为集合选择合适的索引是提高性能的关键。
5.1 索引简介¶
数据库索引与书籍的索引类似。
不使用索引的查询成为全表扫描,也就是说,服务器必须查找完一本完整的书才能找到查询结果。
使用索引是有代价的,对于添加的每一个索引,每次写操作(插入、更新、删除)都将耗时更加多的时间。因此MongoDB限制每个集合上最多只能有64个索引。
5.1.1 复合索引简介¶
索引的值是按一定顺序排列的,因此使用索引键对文档进行排序非常快。然后,只要在首先使用索引键进行排序时才有用。例如,在下面排序中,username上的索引没有什么作用:
db.users.find().sort({'age':1,"username":1})
为了优化这个排序,需要在age 和username上建立索引:
db.users.ensureIndex({'age':1,"username":1})
这样就建立了一个复合索引,如果查询中多有个排序方向或者查询条件中有多个键,这个索引就非常有用。
5.1.2 使用复合索引¶
在多个键上建立的索引就是符合索引。复合索引比单键索引要复杂一些,但是也更强大。
1.选择键的方向
到目前为止,我们的所有索引都是升序的,但是,如果需要在两个或者多个查询条件上进行排序,可能需要要让索引键的方向不同。
为了在不同方向上优化这个复合排序,需要使用与方向相匹配的索引。
只有基于多个查询条件进行排序时,索引方向菜市比较重要的。
2.使用覆盖索引
如果你的查询只需要朝赵索引中包含的字段,那就根本没必要获取实际的文档,当一个索引包含用户请求的所有字段,可以认为这个索引副高了本次查询。在实际中,应该优先使用覆盖索引,而不是去获取实际的文档。
3.隐式索引
略
5.1.3 $操作符如何使用索引¶
有一些查询完全无法使用索引,也有一些查询能够比其他查询更搞笑的i使用索引。
1.低效率的操作符
有一些查询完全无法使用索引,比如 $where 查询和检查一个键是否存在的查询。也有其他一些操作不能高效的使用索引。
2.范围
复合索引使MongoDB能够高效地执行用友多个语句的查询。设计基于多个字段的索引时,应该将会用于精确匹配的字段放在索引的前面,将用于范围的字段放在最后。
3.or查询
通常来说,执行两次查询再将结果合并的效率不如单次查询高,因此应该尽量使用 $in 而不是使用 $or
5.1.4 索引对象和数组¶
MongoDB允许深入文档内部,对嵌套字段和数组建立索引。
5.2 使用explain() 和 hint()¶
从上面的内容可以看出,explain()能够提供大量与查询相关的信息。对于速度比较慢的查询来说,这是最重要的诊断工具之一。
最常见的explain()输出有两种类型:所用索引的查询和没有使用索引的查询。
查询优化器
MongoDB的查询优化器与其他数据库稍有不同,基本来说如果以索引能够精确匹配一个查询,那么查询优化器就会使用这个索引,不然的话,可能会有几个索引都适合你的查询。MongoDB会从这些可能的索引子集中为每次查询计划选择一个,这些查询计划是并行执行的。
这个查询计划会被缓存,这个查询接下来都会使用它。直到集合数据发生了比较大的变动。如果在最初的计划评估之后集合发生了比较大的数据变动,查询优化器就会重新挑选可行的查询计划。
5.3 何时不应该使用索引¶
提取较小的子数据集时,索引非常高效,也有一些查询不适用索引会更快。
索引通常适用的情况 | 全表扫描通常适用的情况 |
---|---|
集合较大 | 集合较小 |
文档较大 | 文档较小 |
选择性查询 | 非选择性查询 |
适用 $natural 排序有一个副作用:返回的结果是按照磁盘上的顺序排列的,对于一个活跃的集合来说,这是没有意义的:随着文档提交的增加或者缩小,文档会在磁盘上进行移动,新的文档会被写入到这些文档留下的空白位置,但是对于只需要进行插入的工作来说,如果要得到罪行的或者最早的文档,使用 $natural就非常有用了。
5.4 索引类型¶
创建索引时可以指定一些选项,使用不同选项简历索引会有不同的行为。
5.4.1 唯一索引¶
唯一索引可以确保集合的每一个文档的指定键都有唯一的值:
db.users.ensureIndex({'username':1},{'unique':true})
有些情况下,一个值可能无法被索引,索引储桶的大小是有限制的。如果某个索引条码超出了他的限制,那么这个条目就不会包含在索引里。
1.复合唯一索引
创建复合唯一索引时,单个键的值可以相同,但所有键的组合值必须是唯一的。
2.去除重复
在极少数情况下,可能希望直接删除重复的值。创建索引时使用dropDups选项,如果遇到重复的值,第一个会被保留,之后的重复文档都会被删除。
"dropDups"会强制性简历唯一索引,但是这个方式太粗暴了:你无法控制哪些文档被保留哪些文档被删除,对于比较重要的数据,千万不要使用"dropDups".
5.4.2 稀疏索引¶
唯一索引会吧null看做值,所以无法将多个缺少唯一索引中的键的文档插入到集合中。然而,在有些情况下,你可以希望唯一索引只对包含相应键的文档生效。如果有一个可能存在也可能不存在的字段,但是他存在是必须是唯一的,这时就可以将unique和sparse选项组合在一起使用。
使用sparse选项就可以创建稀疏索引。
稀疏索引不比是唯一的,只要去掉unique选项,就可以创建一个非唯一的稀疏索引。