読者です 読者をやめる 読者になる 読者になる

カッパでも分かるiOSアプリゲーム開発

カッパがひたすらゲーム制作に関することを書くブログです。Railsに関するTipsもたまにまとめてます。

【Rails】activerecord-import でデータを bulk-insert するのが超便利でイケメン河童になる

Rails
スポンサードリンク

実践Ruby on Rails 4 現場のプロから学ぶ本格Webプログラミング
f:id:InvokeTwoA:20151023183618p:plain「eachして一件ずつ INSERT してたら、大量データ入稿時にタイムアウトしちゃったよ」
f:id:InvokeTwoA:20151215172640p:plain「……それはいけませんなぁ」

bulk-insert でデータを一括入稿する

  • rails なら activerecord-import とかの gem で bulk-insert が簡単に行える
  • 要は 1件ずつ insert しないで一度に一括で insert しちゃおうぜ、という事
  • 3年くらい前からずっとこの方法を使ってるけど超便利で隙がない。なのに今までブログにメモってさえ居なかったのでライブラリ名を忘れるという不始末のカッパ

使い方

gem 'activerecord-import'

f:id:InvokeTwoA:20151023183618p:plain「bundle install して再起動〜 完」
f:id:InvokeTwoA:20151215172640p:plain「ほんと使いやすいライブラリですよねー。ずっとメンテしてくれてるのも吉」

使い方 その2

10.times do |i|
  Book.create! :name => "book #{i}"
end

f:id:InvokeTwoA:20151023183618p:plain「このコードを、下記のように!」

books = []
10.times do |i| 
  books << Book.new(:name => "book #{i}")
end
Book.import books

f:id:InvokeTwoA:20151023183618p:plain「前者だと10回分のSQLの通信が発生してたけど、後者なら1回で済む!」
f:id:InvokeTwoA:20151215172640p:plain「アプリ開発ももっとライブラリまみれになってくれたら良いのになぁ」

効果検証

f:id:InvokeTwoA:20151023183618p:plain「とある仕事で引き受けた、1人につき100件ほどのデータを100人分一気にインポートする作業!」
f:id:InvokeTwoA:20151215172640p:plain「1件ずつINSERT してたら1万回のSQL通信……ごくり」

一件ずつデータを INSERT したとき* bulk-insert で一括入力したとき *
73940ms 27208ms

f:id:InvokeTwoA:20151023183618p:plain「処理時間がこんなにも短く!」
f:id:InvokeTwoA:20151215172640p:plain「SQL通信が少ないのでログにも優しいです」

おまけ

Book.where("id > hoge").destroy_all

これだと対象レコード分のSQL発生

Book.where("id > hoge").delete_all

これならSQL一回だけで済む

f:id:InvokeTwoA:20151023183618p:plain「ふぅー。これでSQLの発行数は激減したはず」
f:id:InvokeTwoA:20151215172640p:plain「でもパフォーマンス改善と同時に細かい所でなんか挙動変わってないか不安になってきました」
f:id:InvokeTwoA:20151023183618p:plain「パフォーマンス改善しました〜  バグが〜 は避けて通れない道だよね。リスクを犯さないものにはうんたらかんたら」

まとめ

f:id:InvokeTwoA:20151023183618p:plain「パフォーマンス改善について聞かれたら、とりあえずSQLの通信料を少なくできないか検討しておきますね〜  みたいなことを言えばそれっぽく聞こえるよね」
f:id:InvokeTwoA:20151215172640p:plain「後はキャッシュとかサーバー台数とかのキーワードを連呼して煙に巻く作戦ですな」