mongodb底层存储和索引原理——本质是文档数据库,无表设计,同时wiredTiger存储引擎支持文档级别的锁,MMAPv1引擎基于mmap,二级索引(二级是文档的存储位置信息『文件id + 文件内offset 』)

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介:

MongoDB是面向文档的数据库管理系统DBMS(显然mongodb不是oracle那样的RDBMS,而仅仅是DBMS)。 想想一下MySQL中没有任何关系型数据库的表,而由JSON类型的对象组成数据模型的样子是如何的?

值得注意的是,MongoDB既不支持JOIN(连接)也不支持transaction(事务)。Significantly, MongoDB supports neither joins nor transactions.

但是请注意MongDB有着大量其他优良的特性,如二级索引、功能丰富的查询语言以及对每一个单个文档文件的原子写保证以及完全一致性的读取。

MongoDB 

rocks1

一、存储引擎(Storage)

    mongodb 3.0默认存储引擎为MMAPV1,还有一个新引擎wiredTiger可选,或许可以提高一定的性能。

    mongodb中有多个databases,每个database可以创建多个collections,collection是底层数据分区(partition)的单位,每个collection都有多个底层的数据文件组成。(参见下文data files存储原理)

    wiredTiger引擎:3.0新增引擎,官方宣称在read、insert和复杂的update下具有更高的性能。所以后续版本,我们建议使用wiredTiger。所有的write请求都基于“文档级别”的lock,因此多个客户端可以同时更新一个colleciton中的不同文档,这种更细颗粒度的lock,可以支撑更高的读写负载和并发量。因为对于production环境,更多的CPU可以有效提升wireTiger的性能,因为它是的IO是多线程的。wiredTiger不像MMAPV1引擎那样尽可能的耗尽内存,它可以通过在配置文件中指定“cacheSizeGB”参数设定引擎使用的内存量,此内存用于缓存工作集数据(索引、namespace,未提交的write,query缓冲等)。

    MMAPv1引擎:mongodb原生的存储引擎,比较简单,直接使用系统级的内存映射文件机制(memory mapped files),一直是mongodb的默认存储引擎,对于insert、read和in-place update(update不导致文档的size变大)性能较高;不过MMAPV1在lock的并发级别上,支持到collection级别,所以对于同一个collection同时只能有一个write操作执行,这一点相对于wiredTiger而言,在write并发性上就稍弱一些。对于production环境而言,较大的内存可以使此引擎更加高效,有效减少“page fault”频率,但是因为其并发级别的限制,多核CPU并不能使其受益。此引擎将不会使用到swap空间,但是对于wiredTiger而言需要一定的swap空间。(核心:对于大文件MAP操作,比较忌讳的就是在文件的中间修改数据,而且导致文件长度增长,这会涉及到索引引用的大面积调整)

    为了确保数据的安全性,mongodb将所有的变更操作写入journal并间歇性的持久到磁盘上,对于实际数据文件将延迟写入,和wiredTiger一样journal也是用于数据恢复。所有的记录在磁盘上连续存储,当一个document尺寸变大时,mongodb需要重新分配一个新的记录(旧的record标记删除,新的记record在文件尾部重新分配空间),这意味着mongodb同时还需要更新此文档的索引(指向新的record的offset),与in-place update相比,将消耗更多的时间和存储开支。由此可见,如果你的mongodb的使用场景中有大量的这种update,那么或许MMAPv1引擎并不太适合,同时也反映出如果document没有索引,是无法保证document在read中的顺序(即自然顺序)。3.0之后,mongodb默认采用“Power of 2 Sized Allocations”,所以每个document对应的record将有实际数据和一些padding组成,这padding可以允许document的尺寸在update时适度的增长,以最小化重新分配record的可能性。此外重新分配空间,也会导致磁盘碎片(旧的record空间)。

    Power of 2 Sized Allocations:默认情况下,MMAPv1中空间分配使用此策略,每个document的size是2的次幂,比如32、64、128、256...2MB,如果文档尺寸大于2MB,则空间为2MB的倍数(2M,4M,6M等)。这种策略有2种优势,首先那些删除或者update变大而产生的磁盘碎片空间(尺寸变大,意味着开辟新空间存储此document,旧的空间被mark为deleted)可以被其他insert重用,再者padding可以允许文档尺寸有限度的增长,而无需每次update变大都重新分配空间。此外,mongodb还提供了一个可选的“No padding Allocation”策略(即按照实际数据尺寸分配空间),如果你确信数据绝大多数情况下都是insert、in-place update,极少的delete,此策略将可以有效的节约磁盘空间,看起来数据更加紧凑,磁盘利用率也更高。

    内存映射存储引擎:MongoDB目前支持的存储引擎为内存映射引擎。当MongoDB启动的时候,会将所有的数据文件映射到内存中,然后操作系统会托管所有的磁盘操作

 

    备注:mongodb 3.2+之后,默认的存储引擎为“wiredTiger”,大量优化了存储性能,建议升级到3.2+版本。

摘自:http://shift-alt-ctrl.iteye.com/blog/2255580

 

数据文件

在MongoDB的数据文件夹中(默认路径是/data/db)由构成数据库的所有文件。每一个数据库都包含一个.ns文件和一些数据文件,其中数据文件会随着数据量的增加而变多。所以如果有一个数据库名字叫做foo,那么构成foo这个数据库的文件就会由foo.ns,foo.0,foo.1,foo.2等等组成。数据文件每新增一次,大小都会是上一个数据文件的2倍,每个数据文件最大2G。这样的设计有利于防止数据量较小的数据库浪费过多的空间,同时又能保证数据量较大的数据库有相应的空间使用。

MongoDB会使用预分配方式来保证写入性能的稳定(这种方式可以使用–noprealloc关闭)。预分配在后台进行,并且每个预分配的文件都用0进行填充。这会让MongoDB始终保持额外的空间和空余的数据文件,从而避免了数据增长过快而带来的分配磁盘空间引起的阻塞。

 

数据存储及索引——更多可以看 http://lib.csdn.net/article/mongodb/53951 recordID本质上是位置信息是『文件id + 文件内offset 』

插入新文档时,MongoDB 会调用底层KV引擎存储文档内容,并生成一个 RecordId 的作为文档的位置信息标识,通过 RecordId 就能在底层KV引擎读取到文档的内容。

如果插入的集合包含索引(MongoDB的集合默认会有_id索引),针对每项索引,还会往底层KV引擎插入一个新的 key-value,key 是索引的字段内容,value 为插入文档时生成的 RecordId,这样就能快速根据索引找到文档的位置信息。

rocks2

如上图所示,集合包含{_id: 1}, {name: 1} 2个索引

  1. 用户插入文档时,底层引擎将文档内容存储,返回对应的位置信息,即 RecordId1
  2. 集合包含2个索引
    • 插入 {_id: ObjectId1} ==> RecordId1 的索引
    • 插入 {name: "rose"} ==> RecordId1 的索引

有了上述的数据,在根据_id访问时文档时 (根据其他索引字段类似)

  1. 根据文档的 _id 字段从底层KV引擎读取 RecordId
  2. 根据 RecordId 从底层KV引擎读取文档内容

摘自:https://toutiao.io/posts/9oxdop/preview 
















本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/bonelee/p/6282072.html,如需转载请自行联系原作者

相关文章
|
6月前
|
NoSQL 测试技术 MongoDB
微服务——MongoDB实战演练——根据上级ID查询文章评论的分页列表
本节介绍如何根据上级ID查询文章评论的分页列表,主要包括以下内容:(1)在CommentRepository中新增`findByParentid`方法,用于按父ID查询子评论分页列表;(2)在CommentService中新增`findCommentListPageByParentid`方法,封装分页逻辑;(3)提供JUnit测试用例,验证功能正确性;(4)使用Compass插入测试数据并执行测试,展示查询结果。通过这些步骤,实现对评论的高效分页查询。
93 0
|
3月前
|
安全 Java 数据库
Jasypt加密数据库配置信息
本文介绍了使用 Jasypt 对配置文件中的公网数据库认证信息进行加密的方法,以提升系统安全性。主要内容包括:1. 背景介绍;2. 前期准备,如依赖导入及版本选择;3. 生成密钥并实现加解密测试;4. 在配置文件中应用加密后的密码,并通过测试接口验证解密结果。确保密码安全的同时,保障系统的正常运行。
286 3
Jasypt加密数据库配置信息
|
11月前
|
存储 NoSQL MongoDB
数据的存储--MongoDB文档存储(二)
数据的存储--MongoDB文档存储(二)
269 2
|
6月前
|
SQL 存储 关系型数据库
数据库的行级锁与表锁?
表锁: 不会出现死锁,发生锁的冲突几率高,并发性低。 存储引擎在进行SQL数据读写请求前,会对涉及到的表进行加锁。 其中锁分为共享读锁和独占写锁:读锁会阻塞写,写锁会阻塞读和写。 行级锁: 会出现死锁,发生锁的冲突几率低,并发性高。 InnoDB引擎支持行锁,与Oracle不同,MySQL的行锁是通过索引加载的,也就是说,行锁是加在索引响应的行上的,要是对应的SQL语句没有走索引,则会全表扫描,行锁则无法实现,取而代之的是表锁,此时其它事务无法对当前表进行更新或插入操作。 行级锁注意事项: 行级锁必须有索引才能实现,否则会自动锁全表,那就不是行锁了。 两个事务不能锁同一个索引。 in
|
7月前
|
关系型数据库 MySQL 网络安全
如何排查和解决PHP连接数据库MYSQL失败写锁的问题
通过本文的介绍,您可以系统地了解如何排查和解决PHP连接MySQL数据库失败及写锁问题。通过检查配置、确保服务启动、调整防火墙设置和用户权限,以及识别和解决长时间运行的事务和死锁问题,可以有效地保障应用的稳定运行。
318 25
|
7月前
|
存储 NoSQL MongoDB
数据库数据恢复—MongoDB数据库迁移过程中丢失文件的数据恢复案例
某单位一台MongoDB数据库由于业务需求进行了数据迁移,数据库迁移后提示:“Windows无法启动MongoDB服务(位于 本地计算机 上)错误1067:进程意外终止。”
|
9月前
|
SQL 存储 关系型数据库
数据库的行级锁与表锁?
表锁:存储引擎在SQL数据读写请求前对涉及的表加锁,分共享读锁和独占写锁,读锁阻塞写,写锁阻塞读写,易发锁冲突,并发性低。行级锁:InnoDB支持,通过索引加锁,提高并发性,但可能引起死锁,需注意索引使用,适用于避免不可重复读场景。
152 21
|
9月前
|
存储 NoSQL MongoDB
【赵渝强老师】MongoDB逻辑存储结构
MongoDB的逻辑存储结构由数据库(Database)、集合(Collection)和文档(Document)组成,形成层次化数据模型。用户通过mongoshell或应用程序操作这些结构。视频讲解及结构图详见下文。
289 3
|
10月前
|
存储 NoSQL 关系型数据库
【赵渝强老师】MongoDB的存储结构
MongoDB 是一个可移植的 NoSQL 数据库,支持跨平台运行。其逻辑存储结构包括数据库、集合和文档,而物理存储结构则由命名空间文件、数据文件和日志文件组成。视频讲解和示意图进一步解释了这些概念。
317 5
|
10月前
|
存储 关系型数据库 MySQL
数据库引擎之InnoDB存储引擎
【10月更文挑战第29天】InnoDB存储引擎以其强大的事务处理能力、高效的索引结构、灵活的锁机制和良好的性能优化特性,成为了MySQL中最受欢迎的存储引擎之一。在实际应用中,根据具体的业务需求和性能要求,合理地使用和优化InnoDB存储引擎,可以有效地提高数据库系统的性能和可靠性。
157 5

推荐镜像

更多