大量レコードをINSERTするときに1回ずつコミットするのと最後にコミットするのとバルクインサート、どれが一番速いか

Pocket

結論:バルクインサートが一番速い。

検証環境

  • ruby 2.1.3
  • activerecord 4.1.7
  • sqlite3
  • バルクインサートの実現にactiverecord-import 0.6.0を使用

検証コードと結果

あらましと考察

  • テストデータを大量に作っては作りなおすときに、最初ふっつーにcreate!でデータを作ってた
  • 重すぎて泣きそうになった
  • Twitterで「毎回コミットしているからでは?」という助言をいただく
  • そういうわけで毎回コミットするのとトランザクションで最後にコミットするのと、ついでにバルクインサートするの、どれが一番速いか試してみた

いずれにしてもバルクインサートが圧倒的に速いが、あえて毎回コミットかトランザクションかで比較すると、100レコードか1000レコードぐらいのオーダーでは若干トランザクションが速い(誤差の範囲な気もするけど・・・)。ただし10000レコードのオーダーになると逆転する。

SQLiteはコミットの度にファイルに書き込む仕様のため、常にトランザクションが優位になると思ったら、そうでもなかった(参考:SQLiteデータベースのチューニング)。このあたりの挙動の理由は、SQLiteにあまり詳しくないので何とも言えない。