[MySQL][Python]8000万レコードをInsertする

概要

・とある物件で8000万弱のレコードを新規のDBに効率的にぶち込む方法を考える必要に
・MySQL(Amazon RDS) + Python(mysql.connector)を想定
・mysql.connector + pythonについては拙文ながら(http://nekopuni.holy.jp/?p=927)に書いております。
・コミットの位置には気をつけよう + Multiple Insert最強ねというお話。

方法その1

まずは最初にやった方法。1レコードごとにInsertしてコミットしていく方法。
今までDB関連でやったコードはレコード量も大したことなかったので以下の方法でも特に問題なかった。

具体的な環境としてはテキストデータ(csv)を読み込み、それをDBにInsertしていくというもの。
csvの中身は日付(DATE)とデータ値(VALUE)がカンマ区切りになっているものであり、エッセンスだけ抜き出すと以下の様なコードを書いていました。

1000レコード弱を処理するのに33秒ほど。8000万行だと30日かかる計算に( д) ゚ ゚
これはイカンザキ

方法その2

コミットするのに時間がかかるということを風のうわさで聞いたので、コミットに時間がかかるのなら最後にコミットすれば良いじゃないというマリーアントワネット作戦

1000レコード弱を処理するのに8秒ほど。たっだ1行のインデントを変えただけで25%ほどの速度で処理できるように。
ただこれでも8000万レコードだと7.5日かかる計算。。

方法その3

どうやら世の中にはMultiple Insertというのがあるらしい。これで1000レコードごとに束ねてInsertすればさらに速度が向上するのでは
以下の例では2レコードのMultiple Insertですが、実際には1000レコード続けて書くようにして実施。

で、出てきたエラー(!)がこちら

なんでやねん!と思ったらAmazon RDSで借りられるデフォルトのDBの容量5GBでは足りていない模様。
ということで急遽100GBまで増額して再トライ。
1000レコードあたりの速度が0.18秒まで高速化!方法その2の3%ほどの速度で処理できるように。

ということで最終的に8000万レコードをぶっ込んだ際にかかった時間が以下

当初30日かかるという無謀な計画が、無事2時間で終えることができました。
最初どんだけ効率悪いコード書いてたんだって話ですねorzorz
Multiple Insert最強ね。

参考

インサート(insert)の処理方式別のパフォーマンスを検証 : 株式会社インターオフィス
http://www.inter-office.co.jp/contents/194/

コメント

  1. Pingback: 【Python】WordPressのテーブルを他のDBのものへ転記する | 自分用のメモ

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">