【问题标题】:Does mongoDB move a document to a new memory location every time a new subDocument is added?每次添加新的子文档时,mongoDB 是否将文档移动到新的内存位置?
【发布时间】:2019-08-30 17:25:59
【问题描述】:

这是一个 MongoDB 数据库的性能问题。

我在看书Learn MongoDB The Hard Way

上下文是如何用Comments 建模/设计BlogPost 的架构,讨论的解决方案是嵌入,如下所示:

{ postName: "..."
, comments: 
    [ { _id: ObjectId(d63a5725f79f7229ce384e1) author: "", text: ""}  // each comment 
    , { _id: ObjectId(d63a5725f79f7229ce384e2) author: "", text: ""}  // is a 
    , { _id: ObjectId(d63a5725f79f7229ce384e3) author: "", text: ""}  // subDocument
    ]
}

在书中他的数据看起来不同,但实际上看起来像我上面的数据,因为推入 subDocuments 列表会创建 _id's

在第二个反驳论点中指出 这种嵌入方法的缺点 - 他这样说:

第二个方面与写入性能有关。随着 cmets 逐渐添加到博客文章中,MongoDB 很难预测在创建新文档时应用正确的文档填充。 MongoDB 需要为不断增长的文档分配新空间。此外,它还必须将文档复制到新的内存位置并更新所有索引。这可能会导致更多的 IO 负载,并可能影响整体写入性能。

提取这个:

此外,它还必须将文档复制到新的内存位置

问题1:这实际上是什么意思?

他指的是什么document..? BlogPost documentComment document

如果他指的是BlogPost document(似乎是这样),这是否意味着整个(小于 16MB)数据被完全重写/复制到硬盘上的新位置-disk,每次我插入一个子文档?

这就是 mongoDB 在后台的实际工作方式?有人可以确认或反驳这一点,因为每次写入移动/复制整个文档似乎是一件大事。尤其是当它向 16MB 的上限增长时。

问题2: 然后,当我更新一个简单的字段时会发生什么?说status: truestatus: false。整个文档会在 HDD 中移动/复制吗?我会说不,其他文档数据应该留在原地,并且更新应该发生在原地(相同的内存位置),但是嗯..不确定了..

更新简单字段与从数组字段中添加或删除子文档之间有区别吗?

我的意思是 - 这个数组操作在某种意义上是特殊的?并触发 HDD 上的文档副本,但简单字段和嵌套对象不会?

如何通过将包含它的字段设置为null 来删除整个大型嵌套对象?这会触发硬盘复制吗?或者不会 - 因为该空间是由于模式的定义而预先分配的......?!

我很困惑。我的项目需要每秒 500 次写入,我正在尝试检测此实现方面是否会影响我。谢谢:)

【问题讨论】:

标签: mongodb database-design nosql database-performance


【解决方案1】:

此行为的许多细节都特定于 MMAPv1 存储引擎 deprecated in MongoDB 4.0。此外,自 MongoDB 3.2 以来的默认存储引擎一直是 WiredTiger,它有一个不同的系统来管理磁盘上的数据。

话虽这么说:

问题1:这实际上是什么意思?

MMAPv1 会将文档写入具有预分配“填充因子”的存储文件,该填充因子为将来添加额外数据提供空白空间。如果以填充不足的方式更新文档,则需要将文档移动到磁盘上的新空间。

实际上,不会增加文档大小的更新(例如,增加一个值,将status: true 更改为status: false 等)可能会在原地执行,而增加文档大小的操作有可能移动文档,因为填充因子可能不足以容纳更大的文档。

here 很好地解释了 MMAPv1 如何在数据文件中管理文档。更多信息可以在here找到。

【讨论】:

    猜你喜欢
    • 2015-12-21
    • 1970-01-01
    • 2021-03-09
    • 2018-07-29
    • 1970-01-01
    • 2020-04-14
    • 1970-01-01
    • 2011-08-04
    相关资源
    最近更新 更多