MongoDB入门之索引(一)

jopen 8年前

索引 就像书的目录,如果查找某内容在没有目录的帮助下,只能全篇查找翻阅,这导致效率非常的低下;如果在借助目录情况下,就能很快的定位具体内容所在区域,效率会直线提高。

首先打开命令行,输入 mongo 。默认mongodb会连接名为 test 的数据库。

➜  ~  mongo  MongoDB shell version: 2.4.9  connecting to: test  > show collections  > 

可以使用 show collections/tables 查看数据库为空。

然后在mongodb命令行终端执行如下代码

> for(var i=0;i<100000;i++) {  ... db.users.insert({username:'user'+i})  ... }  > show collections  system.indexes  users  > 

再查看数据库发现多了 system.indexes 和 users 两个表,前者即所谓的 索引 ,后者为新建的数据库表。

这样 user 表中即有了 10万 条数据。

> db.users.find()  { "_id" : ObjectId("5694d5da8fad9e319c5b43e4"), "username" : "user0" }  { "_id" : ObjectId("5694d5da8fad9e319c5b43e5"), "username" : "user1" }  { "_id" : ObjectId("5694d5da8fad9e319c5b43e6"), "username" : "user2" }  { "_id" : ObjectId("5694d5da8fad9e319c5b43e7"), "username" : "user3" }  { "_id" : ObjectId("5694d5da8fad9e319c5b43e8"), "username" : "user4" }  { "_id" : ObjectId("5694d5da8fad9e319c5b43e9"), "username" : "user5" }

现在需要查找其中任意一条数据,比如

> db.users.find({username: 'user1234'})  { "_id" : ObjectId("5694d5db8fad9e319c5b48b6"), "username" : "user1234" }

发现这条数据成功找到,但需要了解详细信息,需要加上 explain 方法

> db.users.find({username: 'user1234'}).explain()  {      "cursor" : "BasicCursor",      "isMultiKey" : false,      "n" : 1,      "nscannedObjects" : 100000,      "nscanned" : 100000,      "nscannedObjectsAllPlans" : 100000,      "nscannedAllPlans" : 100000,      "scanAndOrder" : false,      "indexOnly" : false,      "nYields" : 0,      "nChunkSkips" : 0,      "millis" : 30,      "indexBounds" : {                },      "server" : "root:27017"  }

参数很多,目前我们只关注其中的 "nscanned" : 100000 和 "millis" : 30 这两项。

nscanned 表示mongodb在完成这个查询过程中扫描的文档总数。可以发现,集合中的每个文档都被扫描了,并且总时间为30毫秒。

如果数据有1000万个,如果每次查询文档都被遍历一遍,时间也是相当可观。

对于此类查询,索引是一个非常好的解决方案。

> db.users.ensureIndex({"username": 1})

然后再查找 user1234

> db.users.ensureIndex({"username": 1})  > db.users.find({username: 'user1234'}).explain()  {      "cursor" : "BtreeCursor username_1",      "isMultiKey" : false,      "n" : 1,      "nscannedObjects" : 1,      "nscanned" : 1,      "nscannedObjectsAllPlans" : 1,      "nscannedAllPlans" : 1,      "scanAndOrder" : false,      "indexOnly" : false,      "nYields" : 0,      "nChunkSkips" : 0,      "millis" : 0,      "indexBounds" : {          "username" : [              [                  "user1234",                  "user1234"              ]          ]      },      "server" : "root:27017"  }

的确有点不可思议,查询在瞬间完成,因为通过索引只查找了一条数据,而不是100000条。

当然使用索引是也是有代价的:对于添加的每一条索引,每次写操作(插入、更新、删除)都将耗费更多的时间。这是因为,当数据发生变化时,不仅要更新文档,还要更新级集合上的所有索引。因此,mongodb限制每个集合最多有64个索引。通常,在一个特定的集合上,不应该拥有两个以上的索引。

小技巧

如果一个非常通用的查询,或者这个查询造成了性能瓶颈,那么在某字段(比如 username )建立索引是非常好的选择。但只是给管理员用的查询(不太在意查询耗费时间),就不该对这个字段建立索引。

</div>

来自: http://segmentfault.com/a/1190000004294447