【问题标题】:Find_each taking ~30 minutes between batchesFind_each 在批次之间大约需要 30 分钟
【发布时间】:2016-02-19 00:48:00
【问题描述】:

我有 260 万条记录正在尝试为其生成公共 ID。本地最多用了3个小时。

在 heroku 上运行 rake 任务需要相当长的时间:

Episode.where(public_id: nil).find_each do |e|
  Rails.logger.info "updating #{e.id} ..."          
  e.set_public_id
  e.save
end

set_public_id 只是生成一个代码并检查它是否重复:

code = generate_code
self.public_id = code
dupe = self.class.where(public_id: self.public_id)

查看记录器输出,它似乎每 30 分钟完成一批 1000 个。我在创建列时确实为:public_id 添加了索引。

我能做些什么来加快速度?

【问题讨论】:

  • 为什么每次都运行重复检查?这可能需要大量的额外时间。既然我假设这是一个你只会运行一次的工作,你为什么不忘记检查重复项,一直运行它,然后在最后检查是否有任何重复项并修复它?这样会快得多,而且如果有的话,您可能只有 1 或 2 个重复项。
  • 好主意!重复检查似乎不会影响本地性能,但这是有道理的。
  • 我也使用了一个名为 activerecord-import 的库,用于批量保存。您可能也想调查一下。 Activerecord 默认不做批量保存,但是 activerecord-import 会添加它。 github.com/zdennis/activerecord-import
  • 在 Heroku 上,您的 vm 正在与其他人共享资源,数据库实例不是本地的,等等。这并不奇怪存在差异。另一种方法而不是 @David 所说的修复方法是查询一次所有非空 id 并将它们保存在内存中的 Set 中。它只有几兆字节。然后在那里进行成员资格测试,而不是每条记录单独查询一次。 @David 的批量上传想法也很棒。
  • 谢谢,这是我第一次接触这种尺寸的东西,所以我想我是懒惰了。您能详细说明将它们保存在内存中的“集合”中吗?不熟悉术语/流程。

标签: ruby-on-rails postgresql activerecord heroku


【解决方案1】:

我认为 find_each 默认批量大小对于 heroku 来说太大了。最终使它起作用的是将批量大小减少到“100”

.find_each(batch_size: 100)

【讨论】:

    【解决方案2】:

    find_each 中决定批处理的大小是一个不错的决定,因为默认批处理大小是 1000,您还可以做的另一件事是将它与.lazyfind_each(batch_size: 100).lazy.each do ... 结合使用

    【讨论】:

      猜你喜欢
      • 2015-03-31
      • 2018-05-14
      • 2012-11-03
      • 1970-01-01
      • 1970-01-01
      • 2015-06-04
      • 1970-01-01
      • 1970-01-01
      • 2017-08-15
      相关资源
      最近更新 更多