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. JS 、JQ 获取宽高总结 & JS中getBoundingClientRect的作用及兼容方案

    1.getBoundingClientRect的作用 getBoundingClientRect用于获取某个html元素相对于视窗的位置集合.   执行 object.getBoundingClien ...

  2. Delphi 中内存映射对于大文件的使用

    这篇文章主要介绍了Delphi 中内存映射对于大文件的使用的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下 Delphi 中内存映射对于大文件的使用 平时很少使用大文件的内存映射,碰巧遇到了 ...

  3. 一款App的开发成本是多少?

    答一: 接触过上万名创业者,开发上线过超过30款App,没有比我更适合回答这个问题的了.. 本文对想做好一款App项目的人来说这是一篇价值百万的回答!因为这是我们花了几百万试错成本试出来的经验! &l ...

  4. Bootstrap历练实例:弹出提示信息的样式按钮

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  5. 一. python基础知识

    第一章.变量与判断语句 1.第一个python程序 # -*- coding:utf-8 -*- # Author: Raymond print ("hello world") p ...

  6. java在线聊天项目0.1版本 制作客户端窗体,使用swing(用户界面开发工具包)和awt(抽象窗口工具包)

    建立Chat项目,并在项目中创建窗口类 package com.swift; import java.awt.BorderLayout; import javax.swing.JFrame; impo ...

  7. 【树形背包】bzoj4033: [HAOI2015]树上染色

    仔细思考后会发现和51nod1677 treecnt有异曲同工之妙 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 ...

  8. mbist summary

    1. 关于mbist,网上也有介绍,觉得不错: 推荐的mbistt的博客:奋斗的猪 2.使用的工具是mbistarchitect,不是tessent. 3.工具使用的相关文档:从EETOP和工具自带的 ...

  9. Linux三剑客之sed详解(1)

    sed (stream editor 流编辑器简写 ) ,用于过滤和转换文本 synopsis sed [option] ... {script-only-if-no-other-script} [i ...

  10. Python9-函数-day9

    初识函数定义与调用 def my_len(): i = 0 for k in s1: i +=1 return i #返回值 # s = 'tim' s1 = '班主任阿娇' length =my_l ...