MongoDB存储引擎(上)——MMAPv1
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的更多相关文章
- MongoDB 存储引擎和数据模型设计
标签: MongoDB NoSQL MongoDB 存储引擎和数据模型设计 1. 存储引擎 1.1 存储引擎是什么 1.2 MongoDB中的默认存储引擎 2. 数据模型设计 2.1 内嵌和引用 2. ...
- MongoDB存储引擎选择
MongoDB存储引擎选择 MongoDB存储引擎构架 插件式存储引擎, MongoDB 3.0引入了插件式存储引擎API,为第三方的存储引擎厂商加入MongoDB提供了方便,这一变化无疑参考了MyS ...
- MongoDB学习笔记(五、MongoDB存储引擎与索引)
目录: mongoDB存储引擎 mongoDB索引 索引的属性 MongoDB查询优化 mongoDB存储引擎: 目前mongoDB的存储引擎分为三种: 1.WiredTiger存储引擎: a.Con ...
- MongoDB 存储引擎选择
MongoDB存储引擎选择 MongoDB存储引擎构架 插件式存储引擎, MongoDB 3.0引入了插件式存储引擎API,为第三方的存储引擎厂商加入MongoDB提供了方便,这一变化无疑参考了MyS ...
- MongoDB 存储引擎:WiredTiger和In-Memory
存储引擎(Storage Engine)是MongoDB的核心组件,负责管理数据如何存储在硬盘(Disk)和内存(Memory)上.从MongoDB 3.2 版本开始,MongoDB 支持多数据存储引 ...
- MongoDB 存储引擎Wiredtiger原理剖析
今天开始看MongoDB 3.2的文档,发现了这么两句话 Support for Multiple Storage Engines MongoDB supports multiple storage ...
- MongoDB存储引擎(中)——WiredTiger
上一篇博文介绍了MongoDB的MMAPv1存储引擎,本文接着介绍MongoDB另一个存储引擎--WiredTiger,WiredTiger是在MongoDB3.0版本引入的,并且在MongoDB3. ...
- mongodb存储引擎
存储引擎(Storage Engine)是MongoDB的核心组件,负责管理数据如何存储在硬盘(Disk)和内存(Memory)上.从MongoDB 3.2 版本开始,MongoDB 支持多数据存储引 ...
- MongoDB存储引擎、索引 原
wiredTiger MongoDB从3.0开始引入可插拔存储引擎的概念.目前主要有MMAPV1.WiredTiger存储引擎可供选择.在3.2版本之前MMAPV1是默认的存储引擎,其采用linux操 ...
随机推荐
- OpenCascade: 获取边的端点
FirstV = TopExp::FirstVertex(aEdge1); LastV = TopExp::LastVertex(aEdge1);
- Sublime Text 套件介紹(四):Pretty JSON
JSON,一個輕量級的資料交換語言,目前許多網站AJAX request的回應結果都是JSON格式 以下是一個標準的JSON格式 { "firstName": " ...
- python之道07
2.用户输入一个数字,判断一个数是否是水仙花数. 水仙花数是一个三位数, 三位数的每一位的三次方的和还等于这个数. 那这个数就是一个水仙花数, 例如: 153 = 1******3 + 5****** ...
- springboot上传linux文件无法浏览,提示404错误
1.配置文件地址置换 @Componentclass WebConfigurer implements WebMvcConfigurer { @Autowired ConfigUtil bootdoC ...
- 洛谷 P2370 P2370 yyy2015c01的U盘
https://www.luogu.org/problemnew/show/P2370 二分+背包 #include <algorithm> #include <iostream&g ...
- 【树形dp 最长链】bzoj1912: [Apio2010]patrol 巡逻
富有思维性的树形dp Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, ...
- 【DB_MySQL】查询语句中各子句的执行顺序
1. FROM 指明查询来源 2. WHERE筛选元组 3. GROUP BY进行分组 4. HAVING 筛选分组 5. SELECT 投影出指定的字段列 6. ORDER BY 对结果集排序 7. ...
- laravel中的路由
相信玩过laravel框架的小伙伴们,都知道它路由的强大之处 今天我想给大家分析下这个 首先 要找到配置路由的位置 routes这个目录下,我们找到web.php文件 里面可以看到现成的一个路由 Ro ...
- 在centos7中为php7安装redis扩展
在此之前一直是用php5.6,安装redis也没遇到啥问题,嗖嗖的就安装上了 更新php版本到php7后,编译的时候报错 include <ext/standard/php_smart_str. ...
- mysql复制延迟排查
今天收到报警,提示从库延时,首先当然是上去查看情况,首先查看机器负载,如下: 可以看到使用cpu已经100%,io没有等待.那么查看mysql是什么情况,执行show processlist没有发现任 ...