例えば以下の場合にSQLが1000回発行されます。
1000.times do Hoge.create(...) end # INSERT INTO hoge (...) # INSERT INTO hoge (...) # INSERT INTO hoge (...) # ...
かなり非効率なのでbulk insertでSQLを1つにまとめて軽量化します。
Railsでbulk insertを実行するためにactiverecord-import
というgemを利用します。
# Gemfile gem 'activerecord-import'
すると、先ほどの処理は以下のように書けます。
hoge_list = [] 1000.times do hoge_list << Hoge.new(...) end Hoge.import hoge_list # INSERT INTO hoge (...), (...), (...), ...
すでにレコードが存在する場合は更新したい
レコードの存在をチェックして、存在する場合は更新、存在しない場合は挿入、ってことをRails側でやろうとするとSQLが大量に発行されて重い処理になってしまいます。
# こんな感じ hoge_ids.each do |hoge_id| hoge = Hoge.find_by(id: hoge_id) if hoge.present? hoge.update(...) else hoge = Hoge.create(...) end end
この場合は、on_duplicate_key_update
オプションを指定することで、MYSQL側で重複を検知して更新するようにします。
hoge_list = [] 1000.times do hoge_list << Hoge.new(...) end # すでにレコードが存在する場合はname, contentカラムを更新するようにする Hoge.import hoge_list, on_duplicate_key_update: [:name, :content] # INSERT INTO hoge (...), (...), (...), ...
バルクインサート、バックアップデートでカンタン軽量化!お試しあれ\(^o^)/