【问题标题】:MongoDB: Does saving a document rewrite the whole document?MongoDB:保存文档会重写整个文档吗?
【发布时间】:2012-06-25 02:28:41
【问题描述】:

我有一个集合domain,其中包含包含域信息的文档。其中一部分是历史 whois 记录,它可能是零个或多个,并且到目前为止占据了文档的大部分空间。

如果我加载整个文档,更改一些小的内容(例如更新数字字段)并使用 save() 方法将 mongo 将整个文档刷新到磁盘或仅更新已更改的 BSON?最终我的问题是,我应该费心用update() 使我的代码复杂化以节省I/O 还是应该只使用save()

这不仅仅是因为懒惰,文档(在完整阅读之后)会经过一系列步骤来修改/处理文档,如果进行了任何更改,则保存整个文档。但是如果保存文档的成本很高,那么也许我必须换一种方式考虑......

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    您可以使用$set 更新文档中的单个字段。这将修改磁盘上的字段。但是,if the document grows beyond the size before the update, the document may have to be relocated on disk

    同时,here is what the documentation says about save versus update

    >// x is some JSON style object
    >db.mycollection.save(x); // updates if exists; inserts if new
    >
    >// equivalent to:
    >db.mycollection.update( { _id: x._id }, x, /*upsert*/ true );
    

    参考文献

    【讨论】:

    • 这很有帮助,但并不能真正回答我的问题。如果我有一个 10mb 的 BSON 文档,我读取它更改一个属性并保存它会再次写入完整的 10mb 吗?假设不必重新定位文档。
    • 关于“就是写的全部”的细节取决于MongoDB使用内存映射文件这一事实。如果您只更新一个属性,那么理想情况下只有那些字节被刷新到磁盘。但是,如果 BSON 变化足够大,那么您可能最终会将整个内容刷新到磁盘。
    • @GatesVP:我认为整个页面都被标记为脏,必须刷新。
    • @SergioTulentsev 你是对的,它会刷新一整页。当然,您也会遇到页面边界上有东西的问题。老实说,这些都是非常深入的内部细节,我很确定这里的答案深藏在源代码中,世界上大约有 10 人真正知道这是如何工作的。
    【解决方案2】:

    这取决于您使用的客户端库。例如,Mongoid(ruby 中的 ODM)足够聪明,只发送已更改的字段(使用$set 命令)。它有时太聪明了,无法捕捉到我对嵌套哈希所做的更改。但我从未见过它发送未更改的字段。

    其他库/驱动程序的行为可能不同。

    【讨论】:

      【解决方案3】:

      我知道这个问题很老,但了解它如何帮助您设计数据库结构非常有用。以下是有关 MongoDB 存储引擎的详细信息: https://docs.mongodb.com/v3.2/faq/storage/

      文档回答了这个问题。基本上,如果您更新 MongoDB 中的整数字段,它会将整数所在的内存中的页面(通常为 4k)标记为脏,并且它将在下一次磁盘刷新时将内存页面写入磁盘。因此,如果您的文档非常大,它可能只会将您的部分文档写入磁盘。

      但是,还有许多其他情况。如果您要向文档填充更多数据,MongoDB 可能需要将整个文档移动到新位置以使文档增长。在这种情况下,整个文档将被写入磁盘。

      【讨论】:

      • 这对我来说很有意义,但我一遍又一遍地浏览文档,但我找不到此信息。我找不到任何明确显示内存页面如何标记为脏并写入磁盘的内容。你能帮我吗?
      猜你喜欢
      • 2020-01-28
      • 1970-01-01
      • 1970-01-01
      • 2011-02-28
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多