mongoDB---索引(转)

来源:互联网 发布:java路径分隔符 编辑:程序博客网 时间:2024/05/22 11:46

mongoDB---索引(转)


索引:
索引通常能够极大的提高查询的效率。在系统中使用查询时,应该考虑建立相关的索引。在MongoDB中创建索引相对比较容易。索引是一种数据结构,他搜集一个集合中文档特定字段的值。MongoDB的查询优化器能够使用这种数据结构来快速的对集合(collection)中的文档(collection)进行寻找和排序.准确来说,这些索引是通过B-Tree索引来实现的。

注:B-tree(多路搜索树,并不是二叉的)是一种常见的数据结构。使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。

一、索引基础:    MongoDB的索引几乎与传统的关系型数据库一模一样,这其中也包括一些基本的优化技巧。下面是创建索引的命令:    > db.test.ensureIndex({"username":1})    可以通过下面的名称查看索引是否已经成功建立:    > db.test.getIndexes()    删除索引的命令是:    > db.test.dropIndex({"username":1})    在MongoDB中,我们同样可以创建复合索引,如:    -- 数字1表示username键的索引按升序存储,-1表示age键的索引按照降序方式存储。    > db.test.ensureIndex({"username":1, "age":-1})    该索引被创建后,基于username和age的查询将会用到该索引,或者是基于username的查询也会用到该索引,但是只是基于
age的查询将不会用到该复合索引。因此可以说,如果想用到复合索引,必须在查询条件中包含复合索引中的前N个索引列。然
而如果查询条件中的键值顺序和复合索引中的创建顺序不一致的话,MongoDB可以智能的帮助我们调整该顺序,以便使复合索引
可以为查询所用。如:    > db.test.find({"age": 30, "username": "stephen"})    对于上面示例中的查询条件,MongoDB在检索之前将会动态的调整查询条件文档的顺序,以使该查询可以用到刚刚创建的复
合索引。    我们可以为内嵌文档创建索引,其规则和普通文档没有任何差别,如:    > db.test.ensureIndex({"comments.date":1})    对于上面创建的索引,MongoDB都会根据索引的keyname和索引方向为新创建的索引自动分配一个索引名,下面的命令可以
在创建索引时为其指定索引名,如:    > db.test.ensureIndex({"username":1},{"name":"testindex"})        随着集合的增长,需要针对查询中大量的排序做索引。如果没有对索引的键调用sort,MongoDB需要将所有数据提取到内存
并排序。因此在做无索引排序时,如果数据量过大以致无法在内存中进行排序,此时MongoDB将会报错。



二、唯一索引:    在缺省情况下创建的索引均不是唯一索引。下面的示例将创建唯一索引,如:    > db.test.ensureIndex({"userid":1},{"unique":true})    如果再次插入userid重复的文档时,MongoDB将报错,以提示插入重复键,如:    > db.test.insert({"userid":5})    > db.test.insert({"userid":5})    E11000 duplicate key error index: test.test.$userid_1  dup key: { : 5.0 }        如果插入的文档中不包含userid键,那么该文档中该键的值为null,如果多次插入类似的文档,MongoDB将会报出同样的错误,
如:    > db.test.insert({"userid1":5})    > db.test.insert({"userid1":5})    E11000 duplicate key error index: test.test.$userid_1  dup key: { : null }            如果在创建唯一索引时已经存在了重复项,我们可以通过下面的命令帮助我们在创建唯一索引时消除重复文档,仅保留发现
的第一个文档,如:    --先删除刚刚创建的唯一索引。    > db.test.dropIndex({"userid":1})     --插入测试数据,以保证集合中有重复键存在。    > db.test.remove()    > db.test.insert({"userid":5})    > db.test.insert({"userid":5})        --创建唯一索引,并消除重复数据。    > db.test.ensureIndex({"userid":1},{"unique":true,"dropDups":true})        --查询结果确认,重复的键确实在创建索引时已经被删除。    > db.test.find()    { "_id" : ObjectId("4fe823c180144abd15acd52e"), "userid" : 5 }            我们同样可以创建复合唯一索引,即保证复合键值唯一即可。如:    > db.test.ensureIndex({"userid":1,"age":1},{"unique":true})   

缺失的键

当一个文档以唯一索引的方式保存到集合中去的时候,任何缺失的索引字段都会一null值代替,因此,不能在唯一索引上同时插入两条缺省

的记录。如下:

  1. >db.things.ensureIndex({firstname: 1}, {unique: true});  
  2.  
  3. >db.things.save({lastname: "Smith"});  
  4.  
  5. >db.things.save({lastname: "Jones"});// 会产生错误,因为firstname会有两个null. 
三、使用explain: explain是非常有用的工具,会帮助你获得查询方面诸多有用的信息。只要对游标调用该方法,就可以得到查询细节。
explain会返回一个文档,而不是游标本身。如:    > db.test.find().explain()    {        "cursor" : "BasicCursor",        "nscanned" : 1,        "nscannedObjects" : 1,        "n" : 1,        "millis" : 0,        "nYields" : 0,        "nChunkSkips" : 0,        "isMultiKey" : false,        "indexOnly" : false,        "indexBounds" : {        }        }    explain会返回查询使用的索引情况,耗时和扫描文档数的统计信息。    "cursor":"BasicCursor"表示没有使用索引。    "nscanned":1 表示查询了多少个文档。    "n":1 表示返回的文档数量。    "millis":0 表示整个查询的耗时。    四、索引管理:    system.indexes集合中包含了每个索引的详细信息,因此可以通过下面的命令查询已经存在的索引,如:    > db.system.indexes.find()    如果在为已有数据的文档创建索引时,可以执行下面的命令,以使MongoDB在后台创建索引,这样的创建时就不会阻塞其他
操作。但是相比而言,以阻塞方式创建索引,会使整个创建过程效率更高,但是在创建时MongoDB将无法接收其他的操作。    > db.test.ensureIndex({"username":1},{"background":true})

注:MongoDB中索引是大小写敏感的。当更新对象是,只有在索引上的这些key发生变化时才会更新。着极大地提高了性能。当对象增长了或者必须移动时,所有的索引
必须更新,这回很慢 。索引信息会保存在system.indexes 集合中,运行 db.system.indexes.find() 能够看到这些示例数据。索引的字段的大小有最大限制,目前接近800 bytes. 可在大于这个值的字段上建立索引是可以的,但是该字段不会被索引,这
种限制在以后的版本中可能被移除。索引的性能索引使得可以通过关键字段获取数据,能够使得快速查询和更新数据。但是,必须注意的是,索引也会在插入和删除的时候增加一些系统的负担。往集合中插入数据的时候,索引的字段必须加入
到B-Tree中去,因此,索引适合建立在读远多于写的数据集上,对于写入频繁的集合,在某些情况下,索引反而有副作用。
不过大多数集合都是读频繁的集合,所以集合在大多数情况下是有用的。使用sort()而不需要索引如果数据集合比较小(通常小于4M),使用sort()而不需要建立索引就能够返回数据。在这种情况下,做好联合使
用limit()和sort()。


转载自:
1.http://blog.csdn.net/mniwc/article/details/8465584
2.http://www.cnblogs.com/stephen-liu74/archive/2012/08/01/2561557.html




0 0
原创粉丝点击