mongodb索引

来源:互联网 发布:s7edge怎么关闭4g网络 编辑:程序博客网 时间:2024/06/10 08:51

简介

索引基础知识:
1. mongodb的索引几乎和传统关系型数据库索引一模一样。
2. 创建索引时,若索引只有一个键则方向无关键要。若是多个键,就得考虑索引的方向问题了。
3. 一般来说,如果索引包含N个键,则对前几个键的查询都会有帮助。比如有个索引{“a”:1,”b”:1,”c”:1…,”z”:1}实际是有了{“a”:1}、{“a”:1,”b”:1}等的索引。但是使用{“b”:1}、{“a”:1,”c”:1}等索引的查询则不会被优化,只有使用索引的前部分的查询才能使用该索引。
4. mongodb的插叙优化器会重排查询项的顺序,以便利用索引:比如查询{“x”:”foo”,”y”:”bar”}的时候,已经有了{“y”:1,”x”:1}的索引,mongodb会自己找到并利用它。
5. 创建索引的缺点是每次插入、更新和删除时都会产生额外的开销。这是因为数据库不但要执行这些操作,还要将这些操作在集合的索引中标记。因此,要尽可能少创建索引。
6. 每个集合默认的最大索引个数是64个,能应付绝大多数情况了。
7. 通过explain和hint工具确保服务器使用了业已建立的索引。
8. 要是查询要返回集合中一般以上的结果,用表扫描会比几乎每条文档都查索引要高效一些。所以,类似查询是否存在某个键或者检查某个布尔的值为真还是为假时,没有用索引的必要。

扩展索引

假设我们有个集合,保存了用户的状态信息。现在想要查询用户和日期,去除某一用户的最近状态。以目前所学,我们会像下面这样创建一个索引:

> db.status.ensureIndex({user:1,date:-1})

这会使对用户和日期的查询非常快,但并不是最好的方式。
假设书籍的索引。有一组文档按照用户名(升序),日期(降序)排序,所以会是这样的情形:
这里写图片描述

这点数据看着还行,但是应用会有数百万的用户,没人每天有数十条状态更新。若是每条用户状态的索引值占用类似一页纸的磁盘空间,那么对于每次最新状态的查询,数据库都会将该用户的不同页索引载入内存。若是站点太热门,内存放不下索引,就会非常慢。
要是改变索引的顺序,变成{date:-1, user:1},则数据库可以将最后几天的索引保存在内存中,可以减少内存交换,这样查询任何用户的最新状态都会快很多。

   所以建立索引时要考虑如下问题:

1. 会做什么样的查询?其中哪些键需要索引?
2. 每个键的索引方向是什么样的
3. 如何应对扩展?有没有种不同的键的排列可以使常用数据更多地保存在内存中?

    要是能回答这些问题,说明你已经做好了索引的准备了。

索引内嵌文档中的键

   内嵌文档的键索引和普通键索引没什么差异。例如,想要按日期索引博客文章的评论,可以在有内嵌文档的“comments”文档组成的数组中对“date”键创建索引:
> db.blog.ensureIndex({"comments.date":1})

内嵌文档的键索引和普通键索引没什么差异,两者也可以联合组成复合索引。

为排序创建索引

随着集合的增长,需要针对查询中大量的排序做索引。如果没有索引的键调用sort,MongoDB需要将所有的数据提取到内存来排序。因此,可以做无索引排序是有个上限的,那就是不可能在内存里面做T级别数据的排序。一旦集合大到不能再内存中排序,MongoDB就会报错。按照排序来索引一边让MongoDB按照顺序提取数据,这样就能排序大规模数据,而不必担心用光内存。

唯一索引

唯一索引可以确保集合的每一个文档的指定键都有唯一的值。例如,如果想保证文档的“username”键都有不一样的值,可以对其创建索引。
一定要牢记默认情况下,ninsert并不检查文档是否已经插入过了。所以,为了避免插入的文档中包含与唯一键重复的值,可能要用安全插入才能满足要求。这样,再插入文档时会看到存在重复键错误提示。“_id”是我们最常见的唯一索引,唯一的一点不同就是不能删除。
如果没有对应的键,索引会将其作为null存储。所以,如果对某个键简历唯一索引,但插入多个缺少该索引键的文档,则由于文档包含null值而导致插入失败。

消除重复

当为已有集合创建索引,可能有些值已经有重复了,这时创建唯一索引就会失败。dropDups选项就可以保留发现的第一个文档,而删除接下来的有重复值得文档:

> db.people.ensureIndex({"username":1},{"unique":true,"dropDups":true})

这种做法多少有点鲁莽,如果数据很重要的话,还是写个脚本做个预处理比较稳妥。

复合唯一索引

创建符合唯一索引的时候单个键的值可以相同,只要所有键的值组合起来不同就好。

使用explain和hint

explain是一个非常有用的工具,会帮你活得查询方面诸多有用信息。只要对游标调用该方法,既可以得到查询细节。

> db.foo.find().explain()

explain会返回查询使用的索引情况(如果有的话),耗时及扫描文档数的统计信息。
当存在多个所以选择的时候,可以用hint强制使用某个索引。多数情况下制定都没必要。MongoDB会帮我们选出合理的索引。
关于explain和hint的具体情况可以参照mongodb权威指南里面的介绍或者查询其它资料。

索引修改

集合的创建可以使用background选项,使这个过程在后台完成,同时正常处理请求。要是不包含background这个选项,数据库会阻塞简历索引期间的所有请求。阻塞的做法会让索引建立的更快,同事也以为这应用在此期间不能应答。
索引的删除可以通过删除索引或者删除集合将索引删除。删除集合的所有文档并不影响索引

0 0