lok*_*oki 2 mongodb wiredtiger
我有一个用户集合.每个用户都有一个经常更新的字段"地理位置"(每次用户显着移动时).由于我希望在更新时在文档级别而不是集合级别上进行并发,因此我使用的是WiredTiger存储引擎.
我了解到,使用WiredTiger,文档中的每次更新都会导致创建新文档:
http://learnmongodbthehardway.com/schema/wiredtiger/
WiredTiger不支持就地更新
但是,本文还说"即使[WiredTiger]不允许就地更新,它仍然可以比许多工作负载的MMAP表现更好 ".这是什么意思?当我使用WiredTiger时,我必须注意哪些具体含义?例如,如果没有就地更新,数据库大小会快速增长吗?还有其他需要注意的事项吗?
我还了解到MongoDB 3.6中的WiredTiger增加了存储增量的功能,而不是重写整个文档(https://jira.mongodb.org/browse/DOCS-11416).这究竟是什么意思?
注意:另外我不明白的是,现在大多数(如果不是全部)硬盘驱动器的扇区大小为4096字节,因此您不能仅向硬盘驱动器写入4个字节(例如),而是必须写入完整块4096字节(首先读取它,更新它中的4个字节,然后写入).由于大多数文档通常<4096字节,这意味着在任何情况下都需要重写整个文档(即使使用MMAP).我错过了什么?
使用MMAPv1存储引擎时,就地更新通常会突出显示为优化策略,因为文档的索引直接指向文件位置和偏移.将文档移动到新的存储位置(特别是如果要更新的索引条目很多),MMAPv1的开销比只需更新更改的字段的就地更新要多.请参阅:MMAPv1中的记录存储特征.
WiredTiger不支持就地更新,因为它在内部使用MVCC(多版本并发控制),这是数据库管理系统常用的.这是对MMAP中简单化视图的重大技术改进,并允许构建更高级的功能,如隔离级别和事务.WiredTiger的索引具有间接级别(引用内部RecordID而不是文件位置和偏移量),因此在存储级别的文档移动不是一个重要的痛点.
但是,本文还说"即使[WiredTiger]不允许就地更新,它仍然可以比许多工作负载的MMAP表现更好".
这意味着尽管MMAPv1可能具有更高效的就地更新路径,但WiredTiger还具有其他优势,例如压缩和改进的并发控制.您可以构建一个工作负载,该工作负载仅包含可能在MMAPv1中执行得更好的一些文档的就地更新,但实际工作负载通常更加多样化.确认给定工作负载的影响的唯一方法是在代表性环境中进行测试.
但是,如果您想要规划未来,MMAPv1与WiredTiger的一般选择没有实际意义:WiredTiger一直是默认存储引擎,因为MMAPv1不支持MongoDB 3.2和一些较新的产品功能.例如,MMAPv1不支持多数读取关注,这反过来意味着它不能用于副本集配置服务器(MongoDB 3.4+中的分片所需)或更改流(MongoDB 3.6+).MMAPv1将在MongoDB(4.0)的下一个主要版本中弃用,目前计划在MongoDB 4.2中删除.
当我使用WiredTiger时,我必须注意哪些具体含义?例如,如果没有就地更新,数据库大小会快速增长吗?
存储结果取决于几个因素,包括架构设计,工作负载,配置和MongoDB服务器的版本.MMAPv1和WiredTiger使用不同的记录分配策略,但两者都会尝试使用标记为free/reusable的预分配空间.通常,WiredTiger在使用存储空间方面更有效,并且还具有压缩数据和索引的优势.MMAPv1 分配额外的存储空间以尝试优化就地更新并避免文档移动,尽管您可以为工作负载不会随时间改变文档大小的集合选择"无填充"策略.
自从MongoDB 3.0首次引入WiredTiger以来,为改进和调整WiredTiger进行了大量投资,因此我强烈建议您使用最新的生产版本系列进行测试,以获得最佳结果.如果您有关于架构设计和存储增长的具体问题,我建议在DBA StackExchange上发布详细信息以供讨论.
我还了解到MongoDB 3.6中的WiredTiger增加了存储增量的功能,而不是重写整个文档(https://jira.mongodb.org/browse/DOCS-11416).这究竟是什么意思?
这是一个实现细节,可以针对某些用例改进WiredTiger的内部数据结构.特别是,MongoDB 3.6+中的WiredTiger可以更有效地处理大型文档的小变化(与之前的版本相比).WiredTiger缓存需要能够返回多个版本的文档,只要它们由开放的内部会话(MVCC,如前所述)使用,因此对于具有小更新的大型文档,存储增量列表可能更有效.但是,如果累积的增量太多(或者增量正在改变文档中的大多数字段),则这种方法可能不如维护完整文档的多个副本.
当数据通过检查点提交到磁盘时,仍需要编写完整版本的文档.如果你想了解一些内部的更多信息,那么在开发支持MongoDB 4.0中的多文档事务的功能之后,会有一系列MongoDB Path To Transactions系列视频.
另外我不明白的是,现在大多数(如果不是全部)硬盘驱动器的扇区大小为4096字节,所以你不能只向硬盘驱动器写入4个字节(例如),而是必须写入4096的完整块bytes(首先读取它,更新其中的4个字节然后再写入).由于大多数文档通常<4096字节,这意味着在任何情况下都需要重写整个文档(即使使用MMAP).我错过了什么?
在不深入了解实现细节并尝试解释所涉及的所有移动部件的情况下,考虑不同的方法如何应用于更新许多文档(而不是单个文档级别)的工作负载以及对内存使用的影响(之前文件写入磁盘).根据文档大小和压缩等因素,单个I/O块可以表示从文档的一小部分(最大大小为16MB)到多个文档的任何位置.
在MongoDB中,一般流程是在内存视图(例如,WiredTiger缓存)中更新文档,在定期刷新到数据文件之前,更改会以快速仅附加日志格式保留到磁盘.如果O/S只需要写入已更改的数据块,则触摸较少的数据块需要较少的总体I/O.
| 归档时间: |
|
| 查看次数: |
1086 次 |
| 最近记录: |