MongoDB学习笔记20MongoDB的索引

MongoDB的索引和关系型数据库的索引概念和功能是相同的:

(1)不使用索引的搜索可以称为全表扫面,也就是说,服务器必须找完整个表才能查询整个结果;

(2)建立索引后搜索,查询在索引中搜索,在索引的条目中找到条目以后,就可以直接跳转到目标文档的位置;这样的搜索比全表的搜索的速度要提高好几个数量级;

先向集合blog中添加1000000个文档:

> for (i=0;i<1000000;i++){
... db.users.insert(
... {"i":i,
... "username":"user"+1,
... "age":Math.floor(Math.random()*120),
... "created":new Date()});}
WriteResult({ "nInserted" : 1 })
>

在上述的集合中随机查询一个文档,使用explain函数来查看搜索过程中的信息:

> db.users.find({"username":"user101"}).explain()
{
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1000000,
"nscanned" : 1000000,
"nscannedObjectsAllPlans" : 1000000,
"nscannedAllPlans" : 1000000,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 7812,
"nChunkSkips" : 0,
"millis" : 344,
"server" : "localhost.localdomain:27017",
"filterSet" : false
}
>

其中millies指明搜索花费的毫秒数为344毫秒;

其中n代表扫描全表后的搜索后的结果数为1,搜索并不知道username为user101的数量到底有几个,为优化查询将查询的结果限制为1个,这样在找到第一个文档后便停止搜索:

> db.users.find({"username":"user101"}).limit(1).explain()
{
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 102,
"nscanned" : 102,
"nscannedObjectsAllPlans" : 102,
"nscannedAllPlans" : 102,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"server" : "localhost.localdomain:27017",
"filterSet" : false
}
>

可以看到millis为0,因为扫描文档的数量极大减少了,查询几乎瞬间完成;

但是这个方法有缺陷,如果找users999999,仍然几乎扫描整个集合。

> db.users.find({"username":"user999999"}).limit(1).explain()
{
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1000000,
"nscanned" : 1000000,
"nscannedObjectsAllPlans" : 1000000,
"nscannedAllPlans" : 1000000,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 7812,
"nChunkSkips" : 0,
"millis" : 321,
"server" : "localhost.localdomain:27017",
"filterSet" : false
}
>

花费几乎和搜索整个集合的的时间millis差不多为321,而且随着文档数量增加,查询花费的时间越长;

在username字段上创建索引:

> db.users.ensureIndex({"username":1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
>

再次查询users999999的用户:

> db.users.find({"username":"user999999"}).limit(1).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" : 85,
"indexBounds" : {
"username" : [
[
"user999999",
"user999999"
]
]
},
"server" : "localhost.localdomain:27017",
"filterSet" : false
}
>

花费的时间millis为85,比没有创建索引前的321要少很多;

当然索引会加快查询的速度,但是也有弊端,每次添加、删除、更新一个文档,MongoDB不仅要更新文档,还要更新文档上的索引;

每个集合只能有64个集合,挑选合适的字段建立索引非常重要。

本文出自 “缘随心愿” 博客,请务必保留此出处http://281816327.blog.51cto.com/907015/1600482

更多相关文章
  • 使用ensureIndex函数创建集合的索引. 对集合而言,每个索引只需要创建一次,重复创建没有任何作用: > show collections system.indexes users 所有的数据库的索引元数据都存放在system.indexs的集合中: 使用getIndexes函数查看给定 ...
  • 创建索引可以指定一些选项,使用不同的选项建立的索引会有不同的行为. 一.唯一索引 唯一索引可以确保每一个文档的指定键都有唯一的值.例如,想确定文档中的username键不重复,创建一个唯一索引: > db.users.findOne() { "_id" : ObjectId ...
  • 索引的值是按照一定顺序排列的,因此使用索引键对文档进行搜索排序比较快:但是只有首先使用索引进行排序时,索引才有用: 例如下面的排序里,"username"上的索引就没有起作用: > db.users.find().sort({"age":1," ...
  • MongoDB中的普通集合是动态的,可以自动增长容纳更多的数据:相对而言,有另一种集合称之为固定集合. (1)固定集合需要实现显式创建,集合大小固定: (2)一旦固定集合中空间用完,插入的新文档将覆盖最老的那个文档的空间,类似循环队列: (3)固定集合不能被分片: (4)固定集合不能修改,只能删除重 ...
  • MongoDB中find查询使用Perl兼容的正则表达式 perl中正则表达式简述:http://www.chinaunix.net/old_jh/25/159388.html 示例: > db.post.find() { "_id" : ObjectId("54 ...
  • 


    		    MongoDB学习笔记11MongoDB的WEB界面
    一.开启Web界面 MongoDB自带一个微型的web管理信息界面,需要修改/etc/mongod.conf中的一个配置项: # Enable the HTTP interface (Defaults to port 28017). httpinterface=true 关闭Mongod服务,手动用 ...
  • GridFS的原理是将大文件分割为多个比较大的块,将每个块作为独立的文档进行存储. (1)GridFS中的块会被存贮到专用的集合中,默认为fs.chunks; (2)除了将文件的每一个块单独存储外,还需要将每个文件块的元信息放入一个文档存储,并将这些文档默认集中在fs.files集合中: 例如将fo ...
  • MongoDB使用游标来处理find查询到的结果文档集: 游标的使用实例: > var cursor=db.post.find({"name.firstname":"joe"}) > cursor { "_id" : Objec ...
一周排行
  • java跨平台的特性使Java越来越受开发人员的欢迎,但也往往会听到不少的抱怨:用Java开发的图形用户窗口界面每次在启动的时候都会跳出一个控制台窗口,这个控制台窗口让本来非常棒的界面失色不少.怎么能够让通过Java ...
  • ########fdisk ll /dev/sda* df -TH fdisk -cul fdisk -cu ~~n~~p~~+1G~~ partx -a /dev/sda ########EXT4 mkfs.ext
  • 直接在TortoiseSVN中修改过往日志,会提示: DAV request failed;it's possible that the repository's pre-revprop-change hook ei
  • openvpn ./easyrsa clean-all ./easyrsa build-ca ./easyrsa gen-req server ./easyrsa sign-req server server ./e
  • 


    		    How to configure dns slave server in Linux
    A DNS server, or name server, is used to reso ...
  • cssboxshadowing
    box-shadow: h-shadow v-shadow blur spread col
  • iOS Sprite Kit教程之滾動場景
    iOS Sprite Kit教程之滚动场景 滚动场景 在很多的游戏中,场景都不是静止的,而 ...
  • 成员变量与局部变量比较,基本类型与引用类型做方法参数,匿名对象   1.成员变量与局部变量比较 在类中的位置不同:成员变量,在方法外. 局部变量,在方法内. 在内存中的位置不同:成员变量,栈内存. 局部变量,堆内存.
  • mvcMVC_Model
    1,Model的职责: Model只负责与数据处理相关的工作. 2,开发Model的基本观
  • UI學習筆記第十二天UITabBarController
    页签视图控制器-UITabBarController   自定义UITabBar