【问题标题】:Mongo script runs quickly locally but slow if I run it against a remote instance?Mongo 脚本在本地运行得很快,但如果我在远程实例上运行它会很慢?
【发布时间】:2014-08-07 18:32:42
【问题描述】:

我有一个 mongo 脚本,用于在数据库迁移后执行一些数据清理。

当我在本地运行此脚本时,它会在大约 5 分钟内完成。当我从本地机器上针对远程实例运行脚本时,它需要很长时间(我通常会在大约两个小时后杀死它)。这些数据库本质上是相同的。索引都是一样的,可能在一个地方有几条记录在另一个地方没有。

我正在执行这样的脚本:

本地-

mongo localDatabase script.js

针对远程实例-

mongo removeServer/remoteDatabase -u user -p password script.js

我假设由于我将脚本传递给远程实例,它将完全在远程机器上执行,无需在远程机器和我的本地机器之间来回传输数据(因此会有性能差异不大)。

这个假设正确吗?知道为什么我看到本地/远程之间的巨大性能差异吗?关于如何修复的建议?

【问题讨论】:

  • 您的脚本正在本地 mongo shell 中执行。导致命中的可能是往返网络时间。你可以 ssh 到远程机器并在那里执行吗?有一个命令可用于在服务器中执行 Javascript,但您不应该使用它。它需要一个全局写锁,阻止所有其他操作。你能分享你的剧本吗?也许有一种方法可以用更少的往返次数来完成同样的事情。
  • 非常有趣,感谢您提供的信息。我可以 ssh 进入远程机器并执行,所以我可能会这样做。您是否碰巧有一个链接,该链接记录了正在发生往返的事情(以及可能为什么这样做)?并不是说我不相信你,但如果可能的话,我只是想读点东西。
  • 这归因于延迟增加确实是一个猜测。当客户端应用程序从本地运行转移到远程位置时,通常会出现问题。如果您可以共享 script.js 文件,我可以帮助确认。
  • 好的,看看这里:pastebin.com/9e1pUp5F
  • 使用此脚本,每个 find.forEach(db.X.update()) 操作都会从 mongod 检索文档,然后一次执行一个更新操作。这就是增加延迟会伤害您的地方。如果运行 MongoDB 2.6,您可以更改它以执行 find() 并构建更新列表,一旦您完成 find 循环,就会在该列表上执行。这将减少往返次数。有关批量 API 的更多信息,请参阅 docs.mongodb.org/manual/reference/method/js-bulk

标签: javascript mongodb performance mongodb-query


【解决方案1】:

是的,您可以使用Bulk operations,MongoDB 中的所有操作都是围绕单个集合设计的,但是循环一个集合并插入或更新另一个集合并没有错。

事实上,在 MongoDB 2.6 shell 中这是最好的方法,并且实际的收集方法本身尝试在后台使用“批量”方法,即使它们实际上每个操作只执行单个更新/插入。这就是为什么您会在 shell 中看到不同的响应。

请注意,您的服务器也需要是 MongoDB 2.6 或更高版本的实例,这就是为什么 shell 中的收集方法会在您连接到较旧的服务器时进行一些检测。

但基本上你的流程是:

    var bulk = db.targetcollection.initializeOrderedBulkOP();
    var counter = 0;

    db.sourcecollection.find().forEach(function(doc) {

        bulk.find({ "_id": doc._id }).updateOne(
            // update operations here
        );
        counter++;

        if ( counter % 1000 == 0 ) {
            bulk.execute();
            bulk = db.targetcollection.initializeOrderedBulkOP();
        }

    });

    if ( counter % 1000 != 0 )
        bulk.execute();

批量 API 本身将使您发送给它的所有操作“排队”,直到调用将操作发送到服务器的执行。 API 本身只会保留任何“排队”操作,直到调用它,但实际上一次只发送 1000 个条目的批次。此处需要特别注意手动使用模数对其进行限制,以避免占用额外的内存。

您可以根据需要调整该数量,但请记住确实存在 16MB 的硬限制,因为这基本上会转换为 BSON 文档作为请求。

请参阅完整的手册页以了解所有选项,包括更新插入、多重更新、插入和删除。甚至是无序的操作,其中单个错误的顺序或失败并不重要。

另请注意,后一种情况下的写入结果将返回列表中的错误项(如果有),以及包含应用这些内容的更新插入列表等内容的响应。

结合让您的 shell 实例尽可能靠近服务器,减少的“来回”流量将加快处理速度。正如我所说,shell 无论如何都在使用这些,所以你不妨利用这些来发挥你的优势。

【讨论】:

    猜你喜欢
    • 2013-07-12
    • 2013-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-26
    • 1970-01-01
    • 2018-01-14
    • 2018-01-22
    相关资源
    最近更新 更多