三招解决MongoDB的磁盘IO问题

标签: MongoDB | 发表时间:2012-04-28 16:51 | 作者:nosqlfan
出处:http://blog.nosqlfan.com

有点标题党的意思,不过下面三招确实比较实用,内容来自 Conversocial公司的VP Colin Howe在London MongoDB用户组的一个分享。

申请:下面几点并非放四海皆准的法则,具体是否能够使用,还需要根据自己的应用场景和数据特点来决定。

1.使用组合式的大文档

我们知道MongoDB是一个文档数据库,其每一条记录都是一个JSON格式的文档。比如像下面的例子,每一天会生成一条这样的统计数据:

{ metric: "content_count", client: 5, value: 51, date: ISODate("2012-04-01 13:00") }
{ metric: "content_count", client: 5, value: 49, date: ISODate("2012-04-02 13:00") }

而如果采用组合式大文档的话,就可以这样将一个月的数据全部存到一条记录里:

{ metric: "content_count", client: 5, month: "2012-04", 1: 51, 2: 49, ... }

通过上面两种方式存储,预先一共存储大约7GB的数据(机器只有1.7GB的内存),测试读取一年信息,这二者的读性能差别很明显:

  • 第一种: 1.6秒
  • 第二种: 0.3秒

那么问题在哪里呢?

实际上原因是组合式的存储在读取数据的时候,可以读取更少的文档数量。而读取文档如果不能完全在内存中的话,其代价主要是被花在磁盘seek上,第一种存储方式在获取一年数据时,需要读取的文档数更多,所以磁盘seek的数量也越多。所以更慢。

实际上MongoDB的知名使用者foursquare就大量采用这种方式来提升读性能。 见此

2.采用特殊的索引结构

我们知道,MongoDB和传统数据库一样,都是采用B树作为索引的数据结构。对于树形的索引来说,保存热数据使用到的索引在存储上越集中,索引浪费掉的内存也越小。所以我们对比下面两种索引结构:

db.metrics.ensureIndex({ metric: 1, client: 1, date: 1})

db.metrics.ensureIndex({ date: 1, metric: 1, client: 1 })

采用这两种不同的结构,在插入性能上的差别也很明显。

当采用第一种结构时,数据量在2千万以下时,能够基本保持10k/s 的插入速度,而当数据量再增大,其插入速度就会慢慢降低到2.5k/s,当数据量再增大时,其性能可能会更低。

而采用第二种结构时,插入速度能够基本稳定在10k/s。

其原因是第二种结构将date字段放在了索引的第一位,这样在构建索引时,新数据更新索引时,不是在中间去更新的,只是在索引的尾巴处进行修改。那些插入时间过早的索引在后续的插入操作中几乎不需要进行修改。而第一种情况下,由于date字段不在最前面,所以其索引更新经常是发生在树结构的中间,导致索引结构会经常进行大规模的变化。

3.预留空间

与第1点相同,这一点同样是考虑到传统机械硬盘的主要操作时间是花在磁盘seek操作上。

比如还是拿第1点中的例子来说,我们在插入数据的时候,预先将这一年的数据需要的空间都一次性插入。这能保证我们这一年12个月的数据是在一条记录中,是顺序存储在磁盘上的,那么在读取的时候,我们可能只需要一次对磁盘的顺序读操作就能够读到一年的数据,相比前面的12次读取来说,磁盘seek也只有一次。

db.metrics.insert([
    { metric: 'content_count', client: 3, date: '2012-01', 0: 0, 1: 0, 2: 0, ... }
    { .................................., date: '2012-02', ... })
    { .................................., date: '2012-03', ... })
    { .................................., date: '2012-04', ... })
    { .................................., date: '2012-05', ... })
    { .................................., date: '2012-06', ... })
    { .................................., date: '2012-07', ... })
    { .................................., date: '2012-08', ... })
    { .................................., date: '2012-09', ... })
    { .................................., date: '2012-10', ... })
    { .................................., date: '2012-11', ... })
    { .................................., date: '2012-12', ... })
])

结果:

  • 如果不采用预留空间的方式,读取一年的记录需要62ms
  • 如果采用预留空间的方式,读取一年的记录只需要6.6ms

来源: www.colinhowe.co.uk

相关文章:
MongoDB的使用挑战
MongoDB构架图分享
MongoDB Hadoop Connector发布
Mongodb Mapreduce 初窥
MongoDB Auto-Sharding 的问题
无觅

相关 [mongodb 磁盘 io] 推荐:

三招解决MongoDB的磁盘IO问题

- - NoSQLFan
有点标题党的意思,不过下面三招确实比较实用,内容来自 Conversocial公司的VP Colin Howe在London MongoDB用户组的一个分享. 申请:下面几点并非放四海皆准的法则,具体是否能够使用,还需要根据自己的应用场景和数据特点来决定. 我们知道MongoDB是一个文档数据库,其每一条记录都是一个JSON格式的文档.

当内存512遇上Access数据库600M,IO磁盘受伤了

- - 博客园_首页
服务器内存就512M,Access数据库(文章库)600多M,结果竟然就是IO受伤了. 秋色园技术原理解析 系列,园里不少看过的帅歌,应该有点印象,从开始到现在,还是铁打的Access数据库. 虽然本人目前对Access恨入之骨,皆因囊中羞涩,暂时不得不与之同流合污. 忙碌 微博粉丝精灵几个月来, 秋色园一直运行正常,除了远程界面都变的很卡之外,基本上也没发现什么异常.

物理IO与逻辑IO

- - 操作系统 - ITeye博客
IO性能对于一个系统的影响是至关重要的. 一个系统经过多项优化以后,瓶颈往往落在数据库;而数据库经过多种优化以后,瓶颈最终会落到IO. 而IO性能的发展,明显落后于CPU的发展. Memchached也好,NoSql也好,这些流行技术的背后都在直接或者间接地回避IO瓶颈,从而提高系统性能. 上图层次比较多,但总的就是三部分.

[mongodb] java操作mongodb

- - 数据库 - ITeye博客
           //实例化Mongo对象,连接27017端口.                               //连接名为yourdb的数据库,假如数据库不存在的话,mongodb会自动建立. //从Mongodb中获得名为yourColleection的数据集合,如果该数据集合不存在,Mongodb会为其新建立.

【MongoDB】MongoDB之优化器Profiler

- - CSDN博客数据库推荐文章
在mysql数据库中,慢查询日志经常作为优化数据库的依据, mongodb中依然有类似的功能. Mongodb自带的profiler,可以方便地记录所有耗时的操作,以便于调优;. 一、开始profiler功能. 开启profier功能有两种:. 第一种就是直接在启动参数里面进行设置,就在茄冬mongodb时候添加-profile=级别.

夜说mongodb

- Lianhui Wang - NoSQLFan
前两天本站刚刚分享了wordnik使用MongoDB经验的文章:《Wordnik 的 MongoDB 使用经历》,今天又看到一位朋友对这方面做的总结,分享在这里,供大家参考. 赋闲以后很长没有更新博客了,说忙完全是借口,多半因为没有兴致所致. 今天凌晨比赛多多,趁着比赛的前奏和间隙,遂浏览些技术文章.

MongoDB与内存

- 高春辉 - 火丁笔记
但凡初次接触MongoDB的人,无不惊讶于它对内存的贪得无厌,至于个中缘由,我先讲讲Linux是如何管理内存的,再说说MongoDB是如何使用内存的,答案自然就清楚了. 据说带着问题学习更有效,那就先看一个MongoDB服务器的top命令结果:. 这台MongoDB服务器有没有性能问题. 先讲讲Linux是如何管理内存的.

白话MongoDB(一)

- Ease - 江边潮未尽,枫红一季秋
按照官方的说法,MongoDB是一种可扩展的高性能的开源的面向文档(document-oriented )的数据库,采用C++开发. 注意mongo不是mango(芒果),这个词是从humongous中截取出来的,其野心不言而明,直指海量数据存储. 和其他很多NoSQL不太一样,MongoDB背后有一个专门的商业公司在提供支持和推广,有点类似MySQL AB的模式.

MongoDB 索引

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