Mongodb 缓存页结构, 为什么我那么快 (1)

本文解析了MongoDB的WiredTiger数据库引擎如何通过页式存储、B-Tree索引、脏页管理、内存跳表和缓存策略,实现高并发写入速度,重点关注内存页面结构、页大小调整及其对性能的影响。

MONGODB 数据库写入和并发的速度,绝非是传统数据库可以比拟的,但到底为什么插入的速度这么快,和他的数据库引擎 wiredTiger 有关,那么就看看MONGODB wiredTiger 的设计。

MONGODB 的数据库引擎WiredTiger, 使用PAGE 页的方式,来存储数据,但是磁盘和内存的页面的结构是不一致的, 内存的页面的结构为B-TREE 结构。

在调用数据的过程中,数据先通过BTREE 索引找到对应的LEAF PAGE 然后在PAGE 内通过二分查找的方式来提取数据。这里根据官方给出的说明 internal page 的大小在 4kb , Leaf page 的大小在 32KB

在leaf page 中存在 dirty leaf page 区域,在插入数据后脏页分为两种,插入数据和更新与删除数据,删除数据与更新是一个类型,删除属于更新标志位.

当在数据库中存在脏页后,通过checkpoint 来将脏页刷新到磁盘,在刷新时避免影响当前的业务,内存中会将需要刷新页面以及他的上层节点和根节点产生一个新的内存的 COPY , 继续工作,老的脏页会进行刷新的操作. 在内存中通过跳表来安排即将通过内存刷新到磁盘的信息与位置.

什么是跳表

https://www.jianshu.com/p/9d8296562806

除定时刷新以外,缓存中的脏页超过阀值,都会触发刷新的工作.

这里的缓存页面主要有

1  memory_page_max 

在内存中的最大的内存页面的大小, 首先这个页面定义成整型的页面,默认值为5MB,这个值主要的作用在于,当对于内存的页面的大小设置,这个页面的大小的设置在于整体内存页面在内存中的申请和分割的原则, 值如果大的情况下,在大量数据写入和频繁更新的情况下,是有利的,内存的页面不会频繁的被执行申请,造成在申请内存页面的时候,会产生卡顿的情况.

2  internal_page_max

这个页面主要存储的内容是每一个leaf page的地址,也是真实每个每个页面的地址.通过internal page中存储的页的地址来找到实际的存储数据的页面. 如果调整internal page 的大小可以控制查找数据的深度,数据量过大会并且internal_page_max 过小会增加查找leaf page的深度, 但过大的internal page 会在本身中进行二分查询leaf page 产生性能问题.

3  leaf_page_max 

leaf 页面是存储实际数据的页面,默认值32KB, 这个是内存中存储数据的页面,调整这个页面的大小可以扩大每个PAGE 存储的数据的容量. 但任何事情都是双刃剑,大型的LEAF PAGE 会提高从 internal_page 中扫描数据的速度,但会加大在本页内进行 二分查找的时间.  同时如果使用SATA 磁盘的情况下,调整leaf_page 的大小有助于顺序数据的读取的速度.

4  allocation_size

分配文件的写入的单元,默认为4KB ,这里不建议调整,调整值的大小与数据考那个键的节省和写入的速度有关.

### MongoDB 为什么MySQL MongoDBMySQL 是两种不同类型的数据库系统,分别适用于不同的应用场景。在某些特定条件下,MongoDB 的性能表现优于 MySQL,主要原因包括以下几点: #### 数据存储方式不同 MongoDB 是一种文档型数据库,数据以 BSON(Binary JSON)格式进行存储,支持嵌套结构和灵活的模式设计。这种方式减少了关系型数据库中常见的多表连接操作,从而提升了查询效率,尤其是在处理非结构化或半结构化数据时更为高效[^1]。 相比之下,MySQL 是关系型数据库,依赖于固定的表结构和外键约束,复杂的 JOIN 操作会显著增加查询延迟。 #### 查询性能优势 对于没有索引 ID 的访问场景,MongoDB 的查询性能全面优于 MySQL,并且不会占用大量 CPU 资源。在千万级别的文档对象中,MongoDB 对有索引 ID 的访问速度与 MySQL 相当,但在无索引访问的情况下,其性能优势更加明显[^3]。 此外,MongoDB 更能充分利用系统内存资源,随着内存容量的增加,其查询速度也相应提升。这是因为 MongoDB 默认将尽可能多的数据缓存内存中,避免了频繁的磁盘 I/O 操作,而 MySQL 的查询缓存机制相对较为保守[^4]。 #### 插入性能对比 在插入操作方面,MongoDB 的性能同样表现出色。测试数据显示,在不指定 `_id` 的情况下,MongoDB 的平均插入速率高于 MySQL 不指定主键插入的速度;而在指定 `_id` 或主键的情况下,MySQL 的插入性能略优[^3]。 #### 系统架构差异 MongoDB 的分布式特性使其更容易实现水平扩展,例如通过分片(Sharding)技术将数据分布在多个节点上,从而提升整体吞吐量。此外,副本集机制支持读写分离,允许将读请求分散到多个从节点,减轻主节点压力。 MySQL 虽然也支持主从复制和读写分离,但其架构更偏向垂直扩展,在高并发写入场景下容易出现瓶颈。 #### 适用场景说明 尽管 MongoDB 在某些场景下性能优于 MySQL,但这并不意味着它可以完全替代关系型数据库。例如,在需要强一致性、复杂事务处理或高度结构化数据管理的场景中,MySQL 仍是更合适的选择。MongoDB 的最终一致性模型可能不适合金融或电商等对数据一致性要求极高的业务[^5]。 --- ### 示例代码:MongoDBMySQL 插入性能对比(伪代码) ```python # MongoDB 插入示例 from pymongo import MongoClient client = MongoClient('localhost', 27017) db = client['test'] collection = db['data'] for i in range(100000): collection.insert_one({"name": f"user_{i}", "age": i % 100}) ``` ```sql -- MySQL 插入示例 INSERT INTO data (name, age) VALUES ('user_1', 25); -- 批量插入可使用 LOAD DATA INFILE 或程序循环插入 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值