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

解决MongoDB磁盘IO问题的三种方法的更多相关文章

  1. IO复用的三种方法(select,poll,epoll)深入理解

    (一)IO复用是Linux中的IO模型之一,IO复用就是进程告诉内核需要监视的IO条件,使得内核一旦发现进程指定的一个或多个IO条件就绪,就通过进程处理,从而不会在单个IO上阻塞了,Linux中,提供 ...

  2. 解决Coursera视频无法观看的三种方法(亲测有效)

      ​   最近在coursera上课时出现了视频黑屏,网页缓冲,无法观看等问题,经过查询发现很多人也有同样的问题.对于不同的原因,一般来说解决方法也不同.这里有三种办法,大家可以挨个尝试,肯定有一个 ...

  3. 【Cocos2d-x游戏开发】解决Cocos2d-x中文乱码的三种方法

    众所周知,Cocos2d-x是一款不错的开源引擎,但是在Cocos2d-x中直接使用中文是无法正确显示的.比如下面的情况: 解决这个问题常用的有三种方法:1.通过转换为UTF-8编码来显示.2.使用i ...

  4. Linux下查看磁盘挂载的三种方法

    Linux下查看磁盘挂载的三种方法 2009-06-05 23:17 好久没有更新日志了,呵呵.不是没有要写的东东.实在抽不出时间来写,要准备公司的考试呢,C++考试.已经有七个月没有写C++代码了, ...

  5. 三种方法解决android帮助文档打开慢

    三种方法解决android帮助文档打开慢   经查是因为本地文档中的网页有如下两段js代码会联网加载信息,将其注释掉后就好了 <link rel="stylesheet" h ...

  6. C#中??和?分别是什么意思? 在ASP.NET开发中一些单词的标准缩写 C#SESSION丢失问题的解决办法 在C#中INTERFACE与ABSTRACT CLASS的区别 SQL命令语句小技巧 JQUERY判断CHECKBOX是否选中三种方法 JS中!=、==、!==、===的用法和区别 在对象比较中,对象相等和对象一致分别指的是什么?

    C#中??和?分别是什么意思? 在C#中??和?分别是什么意思? 1. 可空类型修饰符(?):引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; ...

  7. css - 三种方法解决LI和内部Img的上下间距问题

    在火狐浏览器和谷歌浏览器(qq浏览器,谷歌内核)bug类似这张图: img的高度是190*127 但是放到li中,li并没有设置高度,却和内部的图片之间上下错位. 若强行给li设置高度127,他和im ...

  8. Asp.Net保存session的三种方法 (Dll文件更新导致session丢失的解决办法)

    1. InProc模式(默认值):asp.net将session保存到当前进程中,这种方式最快,但是不能多台服务器共享session,且会话状态数据容易丢失. <sessionState mod ...

  9. 解决移动端浏览器 HTML 音频不能自动播放的三种方法

    https://blog.csdn.net/PY0312/article/details/90349386 由于Android,IOS移动端的浏览器以及微信自带的浏览器为了用户更好的体验,规定不自动播 ...

随机推荐

  1. JavaScript Module Pattern: In-Depth

    2010-03-12 JavaScript Module Pattern: In-Depth The module pattern is a common JavaScript coding patt ...

  2. 可拖拽的ListView

    今天研究了一下可拖拽的ListView ,当ListView的数据不能充满整个模拟器的时候,系统自带的listview上拖下拽都不好使,显得很单调, 为了实现上拖下拽时也能实现滚动的效果,这时候就需要 ...

  3. [蟒蛇菜谱]Python函数参数传递最佳实践

    将函数作为参数传递,同时将该函数需要的参数一起传递.可参考threading.Timer的处理方式: class threading.Timer(interval, function, args=[] ...

  4. mozilla firefox 安装flash player

    下载 flash player http://get.adobe.com/cn/flashplayer/ for linux  .tar.gz文件 install_flash_player_11_li ...

  5. Facebook 帆布接入的总结

    研究接入facebook也有不短的时间, 上线过几款产品,这里把接入所有的点 都记录一下. 1.首先进入facebook的开发者页面,直接入口在右下角更多里面 然后注册开发者账号, 创建APP 选择F ...

  6. failed to push some refs to 'git@github.com:***.git' hint: Updates were rejected b

    使用git push origin master的时候出现一下错误: 解决办法: git push -f origin master 如下:

  7. OD19

    这个程序关掉之后会出现一个NAG窗口  甚是讨厌   于是我们要想办法干掉他,先查壳  发现没有壳  VC写的 加载进一个工具reshecker试试,发现一个我们要找的对话框, 那我们记住这个位置 1 ...

  8. 彻底弄懂Activity四大启动模式

    最近有几位朋友给我留言,让我谈一下对Activity启动模式的理解.我觉得对某个知识点的理解必须要动手操作才能印象深刻,所以今天写一篇博文,结合案例理解Activity启动模式.由于之前看过" ...

  9. 从零开始学习Node.js例子九 设置HTTP头

    server.js //basic server的配置文件 ; var server = require('./basicserver').createServer(); server.useFavI ...

  10. XML代码生成器——XMLFACTORY 简介(三)

    XML代码生成器——XMLFACTORY 简介(三) 这一篇我们讲“类名称”页签 的配置功能,您将了解到:如何为Xml元素指定对应的类名称及脱壳功能. 如果,你没看过这个系列的第一篇文章,请先去看这篇 ...