索引类型

虽然MongoDB的索引在存储结构上都是一样的,但是根据不同的应用层需求,还是分成了唯一索引(unique)、稀疏索引(sparse)、多值索引(multikey)等几种类型。

唯一索引

唯一索引在创建时加上unique:true 的选项即可,创建命令如下:

db.users.ensureIndex({username: 1}, {unique: true})

上面的唯一索引创建后,如果insert一条username已经存在的数据,则会报如下的错误:

E11000 duplicate key error index: gardening.users.$username_1 dup key: { : "kbanker" }

如果你在一个已有数据的collection上创建唯一索引,若唯一索引对应的字段原来就有重复的数据项,那么创建会失败,我们需要加上一个dropDups的选项来强制将重复的项删除掉,命令如下例:

db.users.ensureIndex({username: 1}, {unique: true, dropDups: true})

松散索引

如果你的数据中一些行中没有某个字段或字段值为null,那么如果在这个字段上建立普通索引,那么无此字段或值null的行也会参与到索引结构中,占用相应的空间。如果我们不希望这些值为空的行参与到我们的索引中,这时候可以采用松散索引,松散索引只会让指定字段不为空的行参与到索引创建中来。创建一个松散索引可以用下面的命令:

db.reviews.ensureIndex({user_id: 1}, {sparse: true})

多值索引

MongoDB可以对一个array类型创建索引,比如像下面的结构,MongoDB可以在tags字段上创建索引:

{ name: "Wheelbarrow",
tags: ["tools", "gardening", "soil"]
}

在生成索引时,会为tags中的三个值分别生成三个索引元素,索引中tools,gardening,soil三个值都会指向这同一行数据。相当于分裂成了三个独立的索引项。

索引管理

索引的创建和删除

创建和删除索引的方法有很多种,下面两个是比较原始的方法,通过对system.indexes这个collection进行相应的写操作来完成索引的创建:

spec = {ns: "green.users", key: {‘addresses.zip’: 1}, name: ‘zip’}
db.system.indexes.insert(spec, true)

上面命令往system.indexes中写入一条记录来创建索引,这条记录包含了要在上面创建索引的collection的名字空间,索引的信息,以及索引的名称。

创建完成后,我们可以通过下面命令找到我们创建的索引:

db.system.indexes.find()
{ "_id" : ObjectId("4d2205c4051f853d46447e95"), "ns" : "green.users",
"key" : { "addresses.zip" : 1 }, "name" : "zip", "v" : 0 }

要删除一个已创建的索引,我们可以使用下面的命令来实现:

use green
db.runCommand({deleteIndexes: "users", index: "zip"})

创建索引命令

实际上创建索引还有更方便的命令,那就是ensureIndex,比如我们创建一个open和close两个字段的联合索引,就可以用下面的命令:

db.values.ensureIndex({open: 1, close: 1})

这个命令会触发索引创建的两个过程,一个是将相应的字段排序,因为索引是按B+树来组织的,要构建树,将数据进行排序后能够提高插入B+树的效率(第二个过程的效率),在日志中,你能看到和下面类似的输出:

Tue Jan 4 09:58:17 [conn1] building new index on { open: 1.0, close: 1.0 } for stocks.values
1000000/4308303 23%
2000000/4308303 46%
3000000/4308303 69%
4000000/4308303 92%
Tue Jan 4 09:59:13 [conn1] external sort used : 5 files in 55 secs

第二个过程是将排序好的数据插入到索引结构中,构成可用的索引:

1200300/4308303 27%
2227900/4308303 51%
2837100/4308303 65%
3278100/4308303 76%
3783300/4308303 87%
4075500/4308303 94%
Tue Jan 4 10:00:16 [conn1] done building bottom layer, going to commit
Tue Jan 4 10:00:16 [conn1] done for 4308303 records 118.942secs
Tue Jan 4 10:00:16 [conn1] insert stocks.system.indexes 118942ms

除了日志中的输出外,你还可以通过在终端执行currentOp命令来获取当前操作线程的相关信息,如下例:

> db.currentOp()
{
"inprog" : [
{
"opid" : 58,
"active" : true,
"lockType" : "write",
"waitingForLock" : false,
"secs_running" : 55,
"op" : "insert",
"ns" : "stocks.system.indexes",
"query" : {
},
"client" : "127.0.0.1:53421",
"desc" : "conn",
"msg" : "index: (1/3) external sort 3999999/4308303 92%"
}
]
}

最后一部分就是一个索引构建过程,目前正在执行排序过程,执行到92%。

在后台创建索引

创建索引会对数据库添加写锁,如果数据集比如大,会将线上读写数据库的操作挂起,以等待索引创建结束。这影响了数据库的正常服务,我们可以通过在创建索引时加background:true 的选项,让创建工作在后台执行,这时候创建索引还是需要加写锁,但是这个写锁不会直接独占到索引创建完成,而是会暂停为其它读写操作让路,不至于造成严重的性能影响。具体方法:

db.values.ensureIndex({open: 1, close: 1}, {background: true})

离线创建索引

无论如何,索引的创建都会给数据库造成一定的压力,从而影响线上服务。如果希望创建索引的过程完全不影响线上服务,我们可以通过将replica sets中的节点先从集群中剥离,在这个节点上添加相应的索引,等索引添加完毕后再将其添加到replica sets中。这只需要保证一个条件,就是创建索引的时间不能长于oplog能够保存日志的时间,否则创建完后节点再上线发现再也无法追上primary了,这时会进行resync操作。

索引备份

我们知道,无论是使用mongodump还是mongoexport命令,都只是对数据进行备份,无法备份索引。我们在恢复的时候,还是需要等待漫长的索引创建过程。所以,如果你希望备份的时候带上索引,那么最好采用备份数据文件的方式。

索引压缩

索引在使用一段时间后,经历增删改等操作,会变得比较松散,从而战用不必要的空间,我们可以通过reindex命令,重新组织索引,让索引的空间占用变得更小。

MongoDB索引相关文章-摘自网络的更多相关文章

  1. MongoDB 索引相关知识

    背景: MongoDB和MySQL一样,都会产生慢查询,所以都需要对其进行优化:包括创建索引.重构查询等.现在就说明在MongoDB下的索引相关知识点,可以通过这篇文章MongoDB 查询优化分析了解 ...

  2. mongoDB索引相关

    参考链接:MongoDB索引管理-索引的创建.查看.删除 索引 db.集合名.ensureIndex({"key":1}) 使用了ensureIndex在name上建立了索引.”1 ...

  3. Mongodb 安装 以及 问题解决-摘自网络

    一,下载 1.官网为:http://www.mongodb.org/ :下载安装程序的地址为:http://www.mongodb.org/downloads ,选择选择的是Windows 32-bi ...

  4. HMM相关文章索引

    HMM相关文章索引 1条回复 HMM系列文章是52nlp上访问量较高的一批文章,这里做个索引,方便大家参考. HMM学习 HMM学习最佳范例一:介绍 HMM学习最佳范例二:生成模式 HMM学习最佳范例 ...

  5. MyReport演示下载连接和相关文章索引

    演示地址 Flex集成方式 (旧版2.6) HTML集成方式 MyReport产品站点 NEW 相关文章 ------------------------2.6下面版本号--------------- ...

  6. MySQL 索引原理相关文章

    CSDN的整理: http://bbs.csdn.net/topics/392265880 引擎在磁盘中存储顺序的图解: http://blog.csdn.net/php_lzr/article/de ...

  7. MongoDB(索引及C#如何操作MongoDB)(转载)

    MongoDB(索引及C如何操作MongoDB) 索引总概况 db.test.ensureIndex({"username":1})//创建索引 db.test.ensureInd ...

  8. MongoDB 索引的使用, 管理 和优化

    MongoDB 索引的使用, 管理 和优化 2014-03-25 17:12 6479人阅读 评论(0) 收藏 举报  分类: MongoDB(9)  [使用explain和hint] 前面讲高级查询 ...

  9. 【汇总】涉及iOS&iPhone开发相关文章汇总

    此文章汇总本博客中有涉及iPhone开发的相关文章,不定时更新中... 1.NSUserDefaults快速存储数据: http://www.cnblogs.com/ios-wmm/archive/2 ...

随机推荐

  1. poj - 1191 - 棋盘切割(dp)

    题意:将一个8*8的棋盘(每一个单元正方形有个分值)沿直线(竖或横)割掉一块,留下一块,对留下的这块继续这样操作,总共进行n - 1次,得到n块(1 < n < 15)矩形,每一个矩形的分 ...

  2. java 属性封装

    //封装性 //封装概念: //1.是面向对象思想的三大特征之一 //2.封装细节是隐藏的,仅对外提供访问接口 //3.封装分类: //属性封装 //方法封装 //类的封装 //组件的封装 //模块化 ...

  3. 触发JVM进行Full GC的情况及应对策略

    堆内存划分为 Eden.Survivor 和 Tenured/Old 空间,如下图所示: 从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC,对老年代GC称为M ...

  4. 使用Cookie进行会话管理

    javaweb学习总结(十一)——使用Cookie进行会话管理 一.会话的概念 会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话. ...

  5. android手机导入.cer证书文件的方法

    访问很多https协议的网站需要安装证书,手机也可以导入cer文件,你知道么?本文将通过简单的两步告诉你手机安装cer文件的方法. 步骤一:请先将数字证书文件“******.cer”文件复制到SD卡的 ...

  6. java中pojo、dao命名解释

    POJO::POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称. 使用POJO名称是为了避免和EJB ...

  7. jenkins+maven+junit构建自动化测试,整合junit xml生成直观的测试报告[留存]

    在自动化测试过程中,测试报告最能直观的体现测试的价值,之前一直使用maven+junit来构建我的自动化测试,但这样有几个缺点,一是,不能定时构建自动化任务(也许是我没有找到maven有没有提供这样的 ...

  8. mysql基础拓扑图

    存在的意义,就是体验差异! 01.mysql架构图 02.账户认证流程 03.mysql逻辑结构

  9. 我的第一个Raspberry PI装置

    好吧,我先承认是这是从书上学习的第一个示例. 我入手的是Raspberry红版,版本2,看到这么小巧的卡片电脑可以做这么多事情,真是让人惊喜! 安装系统等都很顺利,启动.安装程序.远程桌面.SSH登录 ...

  10. iOS 10 的一个重要更新-开发 iMessage 的第三方插件

    苹果官方的 Messages 在 iOS 10 推出了非常重大的更新,可能主要是想从其他 IM 巨头手里抢点市场份额回来,包括 Facebook Messenger, Wechat 和 Snapcha ...