MongoDB索引实战技巧

标签: MongoDB Index 索引 | 发表时间:2012-02-05 23:58 | 作者:nosqlfan
出处:http://blog.nosqlfan.com

本文内容源自 Kyle BankerMongoDB In Action一书。主要描述了MongoDB 索引相关的一些基础知识和使用技巧。

索引类型

虽然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"})

创建索引命令

实际上创建索引还有更方便的命令,那就是ensure Index,比如我们创建一个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命令,重新组织索引,让索引的空间占用变得更小。

来源: www.cloudcomputingdevelopment.net

相关文章:

图解 MongoDB 地理位置索引的实现原理

MongoDB的索引使用及索引机制

MongoDB索引内部实现

MongoDB 索引数据类型优化,节省60%内存

10gen工程师讲数据库索引实现
无觅

相关 [mongodb 索引 技巧] 推荐:

MongoDB索引实战技巧

- - NoSQLFan
本文内容源自 Kyle Banker 的 MongoDB In Action一书. 主要描述了MongoDB 索引相关的一些基础知识和使用技巧. 虽然MongoDB的索引在存储结构上都是一样的,但是根据不同的应用层需求,还是分成了唯一索引(unique)、稀疏索引(sparse)、多值索引(multikey)等几种类型.

MongoDB 索引

- - 博客园_首页
索引是用来加快查询的,数据库索引与数据的索引类似,有了索引就不需要翻遍整本书,数据库可以直接在索引中查找,. 使得查询速度很快,在索引中找到条目后,就可以直接跳转到目标文档的位置.. 要掌握如何为查询配置最佳索引会有些难度.. MongoDB索引几乎和关系型数据库的索引一样.绝大数优化关系型数据库索引的技巧同样适用于MongoDB..

MongoDB索引内部实现

- Rehtron - NoSQLFan
在数据库优化中,索引优化是非常重要也是每一个数据库使用者必须了解的. MongoDB的索引采用BTree结构,除了其地理位置索引外,数据索引本质上和MySQL 的 BTree索引没有什么差别. 下面是一个接近200页的PPT,对MongoDB读写操作相关的索引操作进行了图文讲解. 如果你对数据库索引的实现原理感兴趣,可以仔细看看.

MongoDB中索引的用法

- - 数据库 - ITeye博客
本文是一篇转载文章,作者在对 MongoDB文档进行了细致的阅读后,总结出了MongoDB的各种索引的用法. 原文链接: http://iamcaihuafeng.blog.sohu.com/151638529.html. 索引能提高检索数据的速度,你可以想像成在MySQL中创建索引一样,同样索引也是用B-Tree也实现的.

关于Mongodb索引实战

- - snoopyxdy的博客
最近碰到这样的一个需求,一张酒店政策优惠表,我们要根据用户入住和离开的时间,计算一家酒店的最低价政策前10位,数据库表字段如下:. 'hid':88,     酒店id. 'date':20150530,  入住日期整形(不要纠结unix时间戳). 'enable':1,  政策是否启用. 'price':100, 政策价格.

mongodb索引讲解与性能调优

- - haohtml's blog
mongodb索引规则基本上与传统的关系库一样,大部分优化MySQL/Oracle/SQLite索引的技巧也适用于mongodb. 当查询中用到某些条件时,可以对该键建立索引,以提高查询速度. 如果数据量很多且查询多于更新时,可以用索引提高查询的速度. a)         查询索引:. 查询索引很简单,比如说需要查询mailaccess数据库中的Mail collection上的索引时:.

Dex – MongoDB索引优化工具

- - NoSQLFan
Dex是一个开源的MongoDB 优化工具,它通过对查询日志和当前数据库索引进行分析,向管理员提出高效的索引优化策略. 在监控过程中,dex会通过stderr输出推荐的结果. 我们看到,在输出结果中,有一个shellCommand字段,里面就是添加索引的语句,如果你觉得dex的推荐不错,就可以直接复制这段脚本在 MongoDB上添加索引了.

MongoDB范围查询的索引优化

- - NoSQLFan
我们知道, MongoDB的 索引是B-Tree结构的,和MySQL的索引非常类似. 所以你应该听过这样的建议:创建索引的时候要考虑到sort操作,尽量把sort操作要用到的字段放到你的索引后面. 但是有的情况下,这样做反而会使你的查询性能更低. 比如我们进行下面这样的查询:. 查询条件是 {“country”: “A”},按 carsOwned 字段的正序排序.

MongoDB的PHP驱动方法与技巧

- - 运维生存时间
当与mongodb复制集建立连接时,驱动程序首先尝试连接并验证集群中每个非 隐藏的节点. 如果一个节点是“down”状态,将跳过. 然而,如果一个节点是“UP”状态,但是持有写锁,那么验证将没法执行下去,因此该驱动程序将被挂起了. 在mongodb 2.6版本前,在建立索引时的通病. 所有的在前台或后台创建索引,在secondary端将在前台创建.

mysql 索引技巧

- - 小彰
MySQL索引的建立对于MySQL的高效运行是很重要的. 下面介绍几种常见的MySQL索引类型. 在数据库表中,对字段建立索引可以大大提高查询速度. 假如我们创建了一个 mytable表:. CREATE TABLE mytable(   ID INT NOT NULL,    username VARCHAR(16) NOT NULL  );   我们随机向里面插入了10000条记录,其中有一条:5555, admin.