Skip to content
土豆 edited this page Jul 25, 2017 · 4 revisions

索引

MongoDB中的索引,可以看作是书的目录。 想象一下给你一本没有目录的书,然后让你去查询指定内容,我只想说,我不是电脑,我很蛋疼! 让你翻没有目录的书,就跟让电脑查询没有索引的集合一样,从头查询到尾,毫无头绪,我们称这种行为是“表扫描”

索引简介

通常我们要查询一个user的名字,我们是这样的

db.user.find({"username":"william"})

如果我们经常需要对username进行查询,那么我们可以为它建立索引

db.user.ensureIndex({"username":1})

对于同一个集合,索引只需要创建一次,反复创建是徒劳的。

对某个键创建索引会加速对某个键的查询,然而,对于其他键可能没有帮助,即便是查询包含了该索引的键。

总是让电脑进行“毫无头绪”的表扫描也是挺折磨电脑的。 所幸MongoDB也不笨,它会在每次查询后,重排查询项的顺序,自己建立索引。 比如在进行这个查询时,{"x":"foo","y":"bar"},就已经有了 {"x":1,"y":1} 索引了。 每个集合的默认最大索引数是64个。

优vs缺

  • 优:创建索引可以加速我们的查询,提高效率。
  • 缺:每次插入、更新和删除时都会产生额外开销

索引有时并不是最有效的方法,如果查询要返回集合中一半以上的结果,那么通常用表扫描会比用索引效率高一点

索引内嵌文档中的键

对应内嵌文档中的键,我们可以这样添加索引 db.blog.ensureIndex({"comments.date":1})

为排序创建索引

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

索引的名字

集合中每个索引都有一个字符串类型的名字,来唯一标识索引。 服务器通过名字来操作或者删除索引。 要注意的是,索引名有字符个数限制,所以索引创建时一定要用自定义的名字,如

db.user.ensureIndex({"username":1,.......,"date":1},{"name":"XXXX"})

一旦创建索引不成功,可以用getLastError来查看错误提示。

唯一索引

唯一索引可以确保集合的每一个文档的指定键都有唯一值。

db.user.ensureIndex({"username":1},{"uniquer":true})

注意

insert不会检查文档是否插入过了,所以为了避免插入的文档中有与唯一键重复的值,要用安全插入才能满足。

其实_id 是我们最熟悉的唯一索引,它在集合创建时产生,只不过它不能删除!

复合唯一索引

只要满足索引的其中之一不同即可

db.blog.ensureIndex({"username":1,"blogname":1})

作者和作品名其中之一不同即可创建复合唯一索引。

explain() hint()

  • explain()可以返回查询使用的索引情况
  • hint()可以强制cursor使用某索引 但是通常MongoDB 的查询优化器非常智能,会替你选择改用哪一个索引。

地理空间索引

现在有一种查询变得越来越流行(尤其是移动设备):找到离当前位置最近的N个场所。 MongoDB专为平面坐标查询做了专门的索引,称为地理空间索引。

同样需要用ensureIndex创建,不过,参数是两个 "2d"

db.map.ensureIndex({"gps":"2d"})

gps键的值必须是某种形式的一对值:一个包含两个元素的数组或者包含两个键的内嵌文档,像这样

{"gps":[0,100]}

{"gps":{"x":-30,"y":30}}

还可以用min和max设定选项的最大值和最小值

现在我们可以查询

db.map.find({"gps":{"$near":[40,-73]}})

这会按照点(40,-73)由近及远的方式将map集合的所有文档都返回

不仅如此,还可以指定形状,比如矩形

db.map.find({"gps":{"$within":{"$box":[ [10,20],[15,30] ]}}})

$box是两个元素的数组,第一个元素指左下方,第二个指右上角。 还可以用它来找到园内的点

db.map.find({"gps":{"$within":{"$center":[[10,30],5],}}})