Railsでバルクインサート・アップデート

  • 42
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

activerecord-importというgemを利用する。

試した環境

  • Rails 3.2.18
  • activerecord-import 0.5.0

インサート

ノーマルにinsertするときはこんな感じに書く。

100.times do |n|
  Hoge.create!(foo: "foo#{n}", bar: "bar#{n}")
end

このやり方だと100個のINSERT文が個別に走る。
それが嫌だなって時に便利。

バルクインサートを利用して書いてみる。

hoges = []
100.times do |n|
  hoge = Hoge.new(foo: "foo#{n}", bar: "bar#{n}"
  hoges << hoge
end

Hoge.import hoges

こうすると、INSERT文が1つになる。

アップデート

インサートと同じように書ける。

hoges = []
Hoge.find_each do |hoge|
  hoge.foo = "fugafuga"
  hoges << hoge
end

columns = [:id, :foo]
values = hoges.map{|hoge| [hoge.id, hoge.name] }

Hoge.import columns, values, on_duplicate_key_update: [:name]

こう書くと、バルクアップデートが可能。

さらなる高速化を目指すのであれば、
updated_atの更新をしない、validationをオフにする、などの方法がある。
これらは上記の最後の文を以下のように変更すれば実現可能。

Hoge.import columns, values, on_duplicate_key_update: [:name], timestamps: false, validate: false

使いどころはちゃんと考えなゃいけないけど、便利っぽい。