0

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

我正在阅读《Learn MongoDB The Hard Way》这本书

上下文是如何建模/设计 a 的架构,BlogPost讨论Comments的解决方案是像这样嵌入:

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

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

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

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

提取这个:

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

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

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

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

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

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

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

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

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

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

4

1 回答 1

1

MongoDB 4.0 中已弃用的 MMAPv1 存储引擎特有的这种行为的许多细节。此外,自 MongoDB 3.2 以来的默认存储引擎是WiredTiger,它有一个不同的系统来管理磁盘上的数据。

话虽如此:

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

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

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

此处描述了 MMAPv1 如何在数据文件中管理文档的一个很好的解释。更多信息可以在这里找到。

于 2019-08-30T18:16:09.313 回答