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
使いどころはちゃんと考えなゃいけないけど、便利っぽい。