将Mongo数据库中的项目从一台机器更新到多台机器

时间:2012-01-09 21:36:05

标签: mongodb mongodb-.net-driver

我有一个问题,关于更新mongodb集合中每个项目的特定字段的更好策略是什么?我在集合中有大约300万个项目,所有数据库都在一台机器上,没有分片。

显然,可以为集合获取游标并循环遍历每个项目并逐个更新所需的字段,但这似乎不是很有效。当你想从多台机器进行现场更新以加快速度时,你甚至更难做到这一点,你总是担心再次更新相同的项目。我应该提一下,我的数据库的每次提交更新都需要对互联网进行http调用,如果我可以同时进行多个字段更新,则效率更高。

我该怎么做?

我正在使用C#驱动程序。

注意: 我不想使用一个特定值更新项目的所有字段。在我的场景中,我的每个项目都为期望的字段获取不同的值,并且仅为该项目计算新值。换句话说,我可能仍然需要获取每个项目并使用我的逻辑来更新到新值。

我想知道如何同时执行此操作以便我可以同时应用多个项目的逻辑而无需更新项目两次?

我希望能够在多个线程上的一个进程或多个机器上的不同进程中执行此操作?这非常提醒map-reduce中的map进程,其中map-key是对象id,map-value是更新项,reducder是identity reducer,但我不确定MongoDb的map / reduce是否适合这种事。

2 个答案:

答案 0 :(得分:1)

棘手的情况,但这种方法可能是资源效率最高的

  1. “查找”批量(比如1,000)要更新的文档,这些文档当前不在“正在进行中”并检索其_id值。
  2. 在此批次上运行多次更新,使用safe = true write
  3. 将其标记为“正在进行中”
  4. 如果预订成功,则对所有批处理文档执行逻辑
  5. 按新字段值批量订购(意味着,制作最终会有相同字段值的所有文档的列表)
  6. 每个唯一字段值执行HTTP请求和批量更新,设置新字段值并删除“进行中”标记或根据您的功能要求将标记设置为“已处理”。
  7. 这样只有一个线程/进程/机器会更新记录,你有最佳的批量更新,你可以同时运行多个批次而不会干扰另一个。

    所有这一切都说真正的写并发来自单独的分片和分片。没有什么可以阻止你在一台(快速)机器上运行6个mongod守护进程。此外,每个字段值更新必须执行HTTP请求听起来非常低效。 mongo写道(并发或其他)永远不会成为瓶颈。如果HTTP请求是您自己的Web服务,请考虑允许批量请求。最后,此方案可能是架构问题的结果。也许你现在可以让你正在更新的字段引用一组较小的文档。如果你提供更多的背景,我可能会为你找出一些东西。

答案 1 :(得分:0)

这样的东西应该在C#中工作,但我自己无法测试它:

var update = Update.Set("field", "new value");
collection.Update(new BsonDocument(), update, UpdateFlags.Multi, SafeMode.True);

此外,您可能会考虑从服务器shell运行此更新,这可能会更快。这是我能够测试的。用新字段更新一百万(非常简单)的文档花了大约一分钟。用另一个相同大小的值再次更新那些百万个文档花了大约10秒钟(因为它不需要重新组织)。

// where {} searches for all documents,
// {$set : {"field":"new value"}} specifies the field and value to update
// false is for "upsert" behavior
// true is for multi update, updates all matching documents
db.collection.update({}, {$set : {"field":"new value"}}, false, true);