3

我有以下内容:

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 次,也只需要很少的时间。但是,一旦你点击save,突然 ActiveRecord 决定执行 1000 次插入,这非常慢。

我如何编写一个自定义方法,以便它对我建立save_the_bars的所有内容执行单个批量 INSERT 查询(我提醒你,1000 s 显然非常便宜),但它可以作为其中的替代品例子?barsbuildsave


我期待着与这篇博文的建议 #3 一致的答案:

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

但是由于我的示例使用build并依赖于一些稍微不平凡的 rails 魔法,因此如何翻译它并不是很明显。基准奖励积分!

4

1 回答 1

2

我会尝试activerecord-import宝石。

def save_the_bars(bars)
  Bars.import bars
end

这个导入调用对底层数据库适配器执行最有效的操作。很光滑,嗯?

奖励积分:基准


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

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),但我现在对此感到满意。在我的用例中,关闭验证是安全的,因为生成所有Bars 的方法保证生成有效的。

于 2013-09-05T17:43:26.097 回答