如果更新的值大于原始值,我想知道 MongoDB 如何处理字段的更新? 是否重写了整个文档?
例如,如果字段是一个 10 个字符的字符串,而更新是 12 个字符,那么 MongoDB 如何处理更新?
谢谢
答案 0 :(得分:0)
这取决于各种因素,例如驱动程序使用情况、与查询一起传递的选项等。
由于 MongoDB 是 NoSQL,因此默认情况下它没有架构。通常,我们通过数据库驱动程序来实现它。让我们以 mongoose
为例,看看您的问题。
例如,mongoose 驱动程序将 Model 方法分开,例如 findOneAndReplace
和 findOneAndUpdate
。据我所知,Mongo 会更新文档的每个字段,而不是替换它,如果该字段不存在,则创建它。
此外,Mongo has various limits 在每个方法上,例如这里是 aggregation
framework。所以 MongoDB 中的每个文档(无关紧要,作为集合中的单个文档,或者查询聚合的结果)不能超过 16Mb。
因此,在某些情况下,您的文档甚至不会保存在数据库中/从数据库返回。
某些限制可以由 DBA other's are strictly limited, like this 16Mb size of document 手动设置。
答案 1 :(得分:0)
我认为您指的是如 this blog 中所述的就地更新。请注意,该博文来自 11 年前。
这仅适用于 MongoDB 使用内存映射存储引擎的情况。 使用 MMAPv1 存储引擎时,MongoDB 将每个未压缩的数据文件映射到内存中,操作系统会根据需要管理这些文件的进出页面。每个文档都在最后存储了一些空白空间,以便为将来的更新进行填充。
更新文档时,如果新大小小于旧大小加上填充,则可以就地更新。仅当文档增长到足以耗尽填充时才需要重新定位。
在 MMAP 索引中,索引字段值映射到文档的磁盘/文件内位置,因此每次文档移动时,每个包含该文档条目的索引也必须更新。这意味着在重新定位时更新文档至少需要 2 次写入。 MongoDB 允许每个集合最多 64 个索引,如果有这么多索引,重新定位文档需要 65 次写入。
然而,那是那时。
MongoDB 大约在六年前购买了 WiredTiger。自 MongoDB 3.4 左右以来,WiredTiger 存储引擎一直是默认的。 MMAP 在 MongoDB 4.0 中已弃用,在 MongoDB 4.2 中删除了对它的支持。
WiredTiger 存储引擎使用修改后的 B+ tree 存储文档和索引。存储引擎分配一个内部记录标识符作为键,文档作为值存储在B-tree中。
编写一个文档至少需要 2 次写入,一次用于叶页,一次用于 B 树的内部页,对于深树可能多达 5 次。
WiredTiger 使用多版本并发控制,每次更新都需要重写整个文档。但是,WT 中的索引将索引字段值映射到文档的内部记录标识符,该标识符永远不会改变,因此在更新字段时,只需更改实际受修改字段影响的索引。
这使得文档更新需要对文档进行几次写入,并且对每个修改后的索引进行两次写入。 WiredTiger 也有一个内部缓存,因此如果您有多个更新影响 B 树的相同页面,则写入总数可能会减少。
简而言之,MongoDB 根本不再使用就地更新,但当它使用时,它有意在每个文档的末尾包含空白空间,以尽量减少由于变大而需要重新定位的频率。
>