3.0版本以前,MongoDB只有一个存储引擎——MMAP,MongoDB3.0引进了一个新的存储引擎——WiredTiger,同时对原有的MMAP引擎进行改进,产生MMAPv1存储引擎,并将其设置为MongoD3.0的默认存储引擎。然而MMAP引擎的一些弊端在MMAPv1引擎依旧存在,3.2版本开始,MongoDB已将默认的存储引擎设置为WiredTiger。

  作为MongoDB原生的存储引擎,MMAPv1也是有它自己的优势的。MMAPv1基于内存映射文件,它擅长于大容量插入、读取和就地更新的工作负载。本文就先对MMAPv1存储引擎进行介绍。

一、MMAPv1存储引擎的数据组织方式

  使用MMAPv1存储引擎,每个数据库由一个.ns文件和一个或多个数据文件组成,假设数据库名称为mydb,则.ns文件名称为mydb.ns,数据文件名称为:mydb.0,mydb.1,mydb.2....,文件编号从0开始,文件大小从64MB开始,依次倍增,最大为2GB。

  .ns文件实际上是一个hash表,用于快速定位某个集合在数据文件中存储的起始位置。每个数据文件被划分成多个extent,每个extent只包含一个集合的数据,同一个集合的所有extent之间使用双向链表连接,一个extent包含多个文档,同一个extent中的所有文档也使用双向链表连接,所以,同一个集合中所有文档是使用双向链表连接的。

.ns文件的数据组织结构如下:

数据文件的数据组织结构如下:

说明:以上关于.ns文件和数据文件的数据组织结构图是学习另一篇博文之后总结归纳出来的,原文连接:https://yq.aliyun.com/articles/60

  基于这样的数据组织结构,MMAPv1数据的增删改操作实现过程分别如下(各个步骤按优先顺序排列):

1. 新增文档:

(1)优先使用大小合适的已删除文档的空间。

(2)若没有合适的已删除文档空间,则使用大小合适的空闲extent。

(3)若没有大小合适的空闲extent,则创建新的extent,创建过程若数据文件空间不足则创建新的数据文件。

2. 删除文档:

  将删除文档文档插入对应集合的已删除文档链表中,删除文档的空间可以被以后新增的新文档使用,但也有可能因为空间大小不适合新文档而一直无法回收利用,从而产生存储空间碎片造成存储空间的浪费,这种情况可以对集合执行compact命令来整理存储碎片:

db.runCommand({compact: '<collection>'})

3. 更新文档:

(1)若更新后文档变小或不变,直接使用原来空间存放,若有多余空间且足够多,还会将多余空间插入集合的已删除文档链表中以回收利用。

(2)若更新后文档变大,则更新执行过程相当于删除原来文档+新增更新后文档。

二、MMAPv1相对于MMAP的改变

1. 文件空间分配方式不变

  改进后的MMAPv1还是和MMAP一样在数据库级别分配文件,每个数据库中所有的集合和索引都混合存储在数据文件中,磁盘空间无法及时自动回收的问题还是没有得到解决。

  MMAPv1数据文件预分配策略:为了保证连续的存储空间,避免产生磁盘碎片,MMAPv1对数据文件的使用采用预分配策略:数据库创建之后,先创建一个编号为0的文件,大小为64M,当这个文件有一半以上被使用时,再创建一个编号为1的文件,大小是上一个文件的两倍,即128M,依此类推,直到创建文件大小达到2G,以后再创建的文件大小就都是2G了。

2. 锁粒度由库级别锁提升为集合级别锁

  在MMAP中,锁粒度是库级别锁,MMAPv1将其提升为集合级别锁,即同一时刻同一个集合中只能进行一个写操作,在一定程度上提升了数据库的并发处理能力。

3. 文档空间分配方式改变

在MMAP存储引擎中,文档是按照写入顺序排列存储在硬盘中的。如果文档更新后长度变长且原有存储位置后面没有足够的空间放下增长部分的数据,那么文档就要移动到文件中的其他位置,导致集合中所有的索引都要同步修改文档新的存储位置,严重降低了写性能。

  若想避免这种情况的发生,需要在文档后保留一定空间用于存放文档更新后可能增大的部分,为此,MMAP采用两种策略进行文档空间分配:

(1)基于paddingFactor(填充因子)的自适应分配方式

  这种方式会基于每个集合中的文档更新历史计算文档更新的平均增长长度,然后根据平均增长长度设置一个paddingFactor(填充因子,大小大于1), 以后在新文档插入或旧文档移动时分配的空间=文档实际长度×paddingFactor。

(2)基于usePowerOf2Sizes的预分配方式

  这种方式则不考虑更新历史,直接为文档分配比文档大小大而又最接近文档大小的2的N次方大小的存储空间(当大小超过2MB时则变为2MB的倍数增长),例如若文档大小为200Bytes则直接分配256Bytes的空间。

  对于第一种策略,由于每个文档大小不一,经过填充后的空间大小也不一样,如果集合上的更新操作很多,那么因为记录移动而导致的空闲空间会因为大小不一而难以重用。而第二种策略就不一样了,它分配的空间大小都是2的N次方,因此更容易维护和利用。所以,改进后的MMAPv1便抛弃了第一种策略,只使用较优的第二种策略。另外,MongoDB还提供了一个“No Padding Allocation”策略,按照数据的实际尺寸分配空间,如果某个集合上绝大多数情况下执行的都是insert或者in-place update(更新后文档size不会变大),还有极少数的delete,那么可以在这个集合使用这个策略,提高磁盘空间利用率。

三、MMAPv1日志记录

  为了确保对MongoDB数据集的所有修改都持久化到硬盘上,MongoDB默认会将所有的操作日志记录到硬盘上,MMAPv1存储引擎的默认配置是每隔60秒写一次数据文件(可以使用storage.syncPeriodSecs改变写数据文件的时间间隔),每隔100毫秒写一次到日志文件,写日志的频率比写数据文件的频率更高!

四、MMAPv1内存使用

使用MMAPv1存储引擎,MongoDB会自动使用所有机器的空闲的内存作为它的cache,即MongoDB会使用尽可能多的空闲的内存。但MongoDB使用的内存由系统资源监视器监视,由系统控制,可随时回收,如果其他的进程突然需要服务器大量的内存,MongoDB将会让出内存给其他的进程。当然,使用MMAPv1存储引擎的时候,分配的内存越大,MongoDB的性能就越好。

MongoDB存储引擎(上)——MMAPv1的更多相关文章

  1. MongoDB 存储引擎和数据模型设计

    标签: MongoDB NoSQL MongoDB 存储引擎和数据模型设计 1. 存储引擎 1.1 存储引擎是什么 1.2 MongoDB中的默认存储引擎 2. 数据模型设计 2.1 内嵌和引用 2. ...

  2. MongoDB存储引擎选择

    MongoDB存储引擎选择 MongoDB存储引擎构架 插件式存储引擎, MongoDB 3.0引入了插件式存储引擎API,为第三方的存储引擎厂商加入MongoDB提供了方便,这一变化无疑参考了MyS ...

  3. MongoDB学习笔记(五、MongoDB存储引擎与索引)

    目录: mongoDB存储引擎 mongoDB索引 索引的属性 MongoDB查询优化 mongoDB存储引擎: 目前mongoDB的存储引擎分为三种: 1.WiredTiger存储引擎: a.Con ...

  4. MongoDB 存储引擎选择

    MongoDB存储引擎选择 MongoDB存储引擎构架 插件式存储引擎, MongoDB 3.0引入了插件式存储引擎API,为第三方的存储引擎厂商加入MongoDB提供了方便,这一变化无疑参考了MyS ...

  5. MongoDB 存储引擎:WiredTiger和In-Memory

    存储引擎(Storage Engine)是MongoDB的核心组件,负责管理数据如何存储在硬盘(Disk)和内存(Memory)上.从MongoDB 3.2 版本开始,MongoDB 支持多数据存储引 ...

  6. MongoDB 存储引擎Wiredtiger原理剖析

    今天开始看MongoDB 3.2的文档,发现了这么两句话 Support for Multiple Storage Engines MongoDB supports multiple storage ...

  7. MongoDB存储引擎(中)——WiredTiger

    上一篇博文介绍了MongoDB的MMAPv1存储引擎,本文接着介绍MongoDB另一个存储引擎--WiredTiger,WiredTiger是在MongoDB3.0版本引入的,并且在MongoDB3. ...

  8. mongodb存储引擎

    存储引擎(Storage Engine)是MongoDB的核心组件,负责管理数据如何存储在硬盘(Disk)和内存(Memory)上.从MongoDB 3.2 版本开始,MongoDB 支持多数据存储引 ...

  9. MongoDB存储引擎、索引 原

    wiredTiger MongoDB从3.0开始引入可插拔存储引擎的概念.目前主要有MMAPV1.WiredTiger存储引擎可供选择.在3.2版本之前MMAPV1是默认的存储引擎,其采用linux操 ...

随机推荐

  1. beta版本发布-团队

    一.β版本于α版本的不同 1.α版本先前只可电脑单机使用,β版本已成功解决联网问题,可以在不同电脑上正常使用 2.β版本相较于α版本修补了较多漏洞.进行了界面的优化且新增了学生个人信息维护功能.教师的 ...

  2. ftl-server静态资源服务器

    ftl-server 是一前端开发工具,支持解析freemarker模板,模拟后端接口,反向代理等功能. 特性 解析freemarker模板 静态资源服务 mock请求 代理请求 livereload ...

  3. Linux之Nginx服务 nfs文件存储 负载均衡

    一.搭建Nginx服务 Nginx 是俄罗斯人编写的十分轻量级的HTTP 服务器,Nginx,它的发音为"engine X",是一个高性能的HTTP和反向代理服务器,同时也是一个I ...

  4. Python基础篇 -- 字符串

    字符串 字符串是不可变的对象,任何操作对原字符串是不会有任何影响的. 索引和切片 索引 . 索引就是下标, 下标从 0 开始, 使用[] 来获取数据 s1 = "0123456" ...

  5. html制作简单框架网页 实现自己的音乐驿站 操作步骤及源文件下载 (播放功能限mp3文件)

    使用HTML语言来设计制作 Hyper Text Markup Language 超文本标记语言 这门语言的特点就是标记,就是把所有的命令单词用<>标记起来,就可以发挥作用 还有一个特点, ...

  6. ios之UITabelViewCell的自定义(xib实现)

    通过继承UITableViewCell来自定义cell 1.创建一个空的项目.命名: 2.创建一个UITableViewController 并且同时创建xib: 3.设置AppDelegate.m中 ...

  7. 移动产品设计之ios系统的导航

    做道题:[不定项选择题] OS中导航设计模式有几种? A.平铺导航 B.标签导航 C.树形导航 D.模态视图导航 正确答案:A B C 讲解: 导航始终是产品设计的重头戏,往往产品设计中90%的事情就 ...

  8. perl 对ENV环境变量的使用

    1.hash 方式访问. %ENV  key为环境变量名,value为环境变量值 2.调用ENV模块 . use Env qw(PATH); print "path is $ENV{path ...

  9. PHP发送邮件标题乱码的解决

    遇到问题:PHPMailer发送邮件时中文乱码,本来我的系统都是英文内容的,后来需求变化需要在标题中添加中文,但是在使用安卓自带邮件工具收取是出现乱码,而使用QQ邮箱查看确实正常的. 解决方法: 先用 ...

  10. Python基础-__main__

    Python基础-_main_ 写在前面 如非特别说明,下文均基于Python3 一.__main__的官方解释 参考 _main_ -- Top-level script environment ' ...