【问题标题】:Partial doc updates to a large mongo collection - how to not lock up the database?对大型 mongo 集合的部分文档更新 - 如何不锁定数据库?
【发布时间】:2013-12-21 14:27:21
【问题描述】:

我有一个 mongo db 实例,其中有一个集合,其中包含大约 1700 万条记录。

我希望更改所有 1700 万个文档的文档结构(在文档中添加一个新属性),这样我就不必麻烦地处理不同的结构,并使查询更易于编写。

但有人告诉我,如果我运行更新脚本来执行此操作,它将锁定整个数据库,可能会导致我们的网站瘫痪。

在不发生这种情况的情况下更改文档的最简单方法是什么? (我不介意更新是否缓慢,只要它最终发生)

我正在尝试做的查询是:

db.history.update(
  { type : { $exists: false }},
  {
    $set: { type: 'PROGRAM' }
  },
  { multi: true } 
)

【问题讨论】:

  • 请发布您当前的更新查询。您使用的更新运算符与答案相关。
  • 感谢 Calimero 的提示,我已添加查询

标签: mongodb


【解决方案1】:

您可以分批更新集合(比如每批一百万),这将分配负载。

我创建了一个包含 20000000 条记录的集合,并在其上运行了您的查询。在虚拟机上更新大约需要 3 分钟,我仍然可以在单独的控制台中从数据库中读取数据。

> for(var i=0;i<20000000;i++){db.testcoll.insert({"somefield":i});}

mongo 中的锁定非常轻量级,并且不会在整个更新期间保持。把它想象成 20000000 次单独的更新。你可以在这里阅读更多:

http://docs.mongodb.org/manual/faq/concurrency/

【讨论】:

  • 有没有简单的方法来批量查询?或者是 find() 查询的情况,使用游标并循环遍历结果,一次更新 1 个文档。
【解决方案2】:

确实真正关心你的更新查询是否很慢,因为你知道的数据库上的写锁问题,两者都是紧密联系的。这里不是一个简单的读查询,你真的希望这个写查询尽可能快。

更新“查找”部分是这里的关键部分。首先,由于您的集合包含数百万个文档,因此最好使字段名称的大小尽可能小(最好是单个字符:type => t)。由于 mongodb 集合的无模式特性,这很有帮助。

其次,更重要的是,您需要使查询使用适当的索引。为此,您需要解决未优化的 $exists 运算符(实际上有几种方法可以做到)。

第三,您可以自己处理字段值。使用http://bsonspec.org/#/specification 估计您要存储的值的大小,并最终选择一个更好的选择(在您的情况下,您可以用数字常量替换“PROGRAM”字符串并在此过程中获得几个字节,乘以每次更新多个查询要更新的文档数)。要写入的数据越小,操作就越快。

一些可以启发你的其他问题的链接:

Can MongoDB use an index when checking for existence of a field with $exists operator?

Improve querying fields exist in MongoDB

【讨论】:

    猜你喜欢
    • 2018-05-18
    • 2023-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多