ruby-on-rails - Rails 批量构建和保存

标签 ruby-on-rails ruby database optimization activerecord

我有类似下面的内容:

module Bar < ActiveRecord::Base
  belongs_to :foo
  ...

module Foo < ActiveRecord::Base
  has_many :bars, dependent: :destroy

  def build_bars
    1000.times do |i|
      bars.build(num: i)
    end
  end

  def create_default_bars!
    build_bars
    save
  end

请注意 Foo#build_bars 很便宜。即使它循环 1000 次,也只需要很少的时间。但是,一旦您点击保存,ActiveRecord 突然决定执行 1000 次插入,这非常慢。

我如何编写自定义 save_the_bars 方法,以便它对我建立的所有 bars 执行单个批量 INSERT 查询(我提醒你,1000 build 显然非常便宜),但是在这个例子中哪个功能可以替代 save


我期待按照这篇博文的建议 #3 给出的答案:

https://www.coffeepowered.net/2009/01/23/mass-inserting-data-in-rails-without-killing-your-performance/

但由于我的示例使用 build 并依赖于一些稍微重要的 rails 魔法,因此如何转换它并不是很明显。基准测试的奖励积分!

最佳答案

我会尝试 activerecord-import gem 。

def save_the_bars(bars)
  Bars.import bars
end

This call to import does whatever is most efficient for the underlying database adapter. Pretty slick, eh?

奖励积分:Benchmarks


提问者在这里,劫持这个答案,详细说明我按照上述建议做了什么:

def build_bars
  built_bars = []
  1000.times do |i|
    built_bars << bars.build(num: i)
  end
  built_bars
end

def create_default_bars
  save
  Bar.insert built_bars, validate: false
  reload
end

这以相对较少的努力提供了不错的加速。我仍然怀疑可以有更多的加速(通过利用 insert 的细微差别),但我现在对此感到满意。在我的用例中,关闭验证是安全的,因为生成所有 Bar 的方法保证生成有效的。

关于ruby-on-rails - Rails 批量构建和保存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18642528/

相关文章:

ruby-on-rails - heroku 不加载语言文件

ruby-on-rails - 如何从父 Controller 保存我的子记录?

javascript - 尝试在不同域上使用 CORS 和 XSRF

ruby - 是否应该传入 block 变量,即使它们未被使用?

php - RedBean 是否需要 "id"主键?

PHP 表单到数据库

mysql - 修改 SQL 查询以仅获取过去 2 个月的数据

ruby-on-rails - Rails 有很多通过多态的复选框

ruby-on-rails - 负载测试期间 Unicorn CPU 使用率激增,优化方法

ruby-on-rails - 部署后等待迁移