DBへの一括INSERT

半分仕事なんだけど、スクリプト言語などを使ってDBへログなんかをパースしながら大量にINSERTするときの方法について少し調査。
普通の方法としては、perlのDBDなんかのマニュアルにある通りprepareして、bindparamして、executeするというのがあたり前だろう。しかしMySQLのドキュメントによれば、大量のINSERTをするときはマルチプル INSERTを使えとある。ようはINSERT文のVALUE以降を追加したいタプルだけつらつらと列挙するというもの。ループ中でどんどん長いSQLにしていって、適当なところで実行するイメージだろう。
prepareするとDBMSの方で文法解析まではやってくれるので、結構効率が良さそうだけど、長いSQLにした方が行き来が少なくていいような気もする。
んで、簡単なスクリプトを書いて実験してみた

  • 両方式で差は1割未満だった
  • どちらかと言うとマルチプル INSERT の方が速かった
  • bindparamはエスケープを良きにはからってくれるが、multiple-insertは自分でやらなきゃだめ(少なくととも今回の方法では)
  • 後者のエスケープのは処理方が実行速度に影響しているようだ(丁寧にパースする処理を追加していくと処理時間が逆転した)
  • INSERT自体の処理よりも前処理の方が支配的
  • その前処理を任せられるprepareの方が、トータルとして便利だと思われる
  • 関係ないけど、日付の処理が面倒だな。rubyだとrfc2822とか数種類の形式をサポートしているけど、apacheのCLF形式のフォーマットには対応していないのね

ということで、よりprepareでSQLを準備する方式を使っていこうと思う。
他には前処理だけをscriptでやってファイルに書き出した後にload data fileで一括して突っこんだときとの比較もやりたい。