每次添加新的子文档时,mongoDB 是否将文档移动到新的内存位置?

Does mongoDB move a document to a new memory location every time a new subDocument is added?

这是 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

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

The second aspect relates to write performance. As comments get added to Blog Post over time, it becomes hard for MongoDB to predict the correct document padding to apply when a new document is created. MongoDB would need to allocate new space for the growing document. In addition, it would have to copy the document to the new memory location and update all indexes. This could cause a lot more IO load and could impact overall write performance.

提取这个:

In addition, it would have to copy the document to the new memory location

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

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

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

这就是 mongoDB 的实际工作原理?有人可以证实或反驳这一点,因为每次写入 move/copy 整个文档似乎都是一件大事。特别是当它增长到 16MB 的上限时。

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

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

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

如何通过使包含它的字段 null 来删除整个大嵌套对象?这会触发硬盘复制吗?或者不会 - 因为 space 是预先分配的,因为模式是如何定义的......?!

我很困惑。我的项目将需要 500 writes/second,我正在尝试检测此实施方面是否会影响我。谢谢:)

此行为的许多细节特定于 MMAPv1 存储引擎 deprecated in MongoDB 4.0. Additionally, the default storage engine since MongoDB 3.2 has been WiredTiger,它具有不同的系统来管理磁盘上的数据。

也就是说:

Question1: What does this mean actually?

MMAPv1 会将文档写入具有预分配 "padding factor" 的存储文件中,该文件提供空 space 以供将来添加其他数据。如果以填充不足的方式更新文档,则需要将文档移动到磁盘上的新 space。

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

很好地解释了 MMAPv1 如何管理数据文件中的文档here. More information can be found here