SQLiteでINSERTが激しく遅い件
さて、表題そのまんまです。
で、残念ながら高度なチューニングなんかの話ではなく、おそらく基本的な話です。けど、知らないとハマるかも。
とあるAndroidアプリの開発で、テーブルに20万件ほどのレコードを登録しないといけなくなりました。
で、Androidアプリで使うDBはSQLiteなので、SQLiteでテーブルつくってINSERTをループさせる方法で実装。
くっそ遅い!!
INSERT終わるまで1時間以上かかるんですわ。
で、ちょっとググってみたところ、SQLiteのINSERTメソッド、内部でトランザクション管理してるみたいです。
なので、以下のようにやっちゃうと20万回トランザクションを開始→コミットってやってて、そのコストが激しくバカにならない。
SQLiteDatabase dbh; // 適当にインスタンスを生成しておく for (int i = 0 ; i < 200000 ; i++) { // 適当にINSERT dbh.insert(table, nullColumnHack, values); }
まあ、ここまで書いた時点で解決策は出てますが、トランザクション管理を明示的にやります。
SQLiteDatabase dbh; // トランザクション開始 dbh.beginTransaction(); for (int i = 0 ; i < 200000 ; i++) { // 適当にINSERT dbh.insert(table, nullColumnHack, values); } // コミットしてトランザクション終了 dbh.setTransactionSuccessful(); dbh.endTransaction();
件数が多いと、めっさ速くなります。
というか、そもそもが遅すぎただけなんですが。
Oracleさんとかだと、大量のundoためた状態でコミットするとけっこうな時間を取られますが、SQLiteは上記の20万件程度ならコミットも一瞬です。
内部実装ってどうなってんだろ? SQLiteは普通にファイルに保存してるはずだから、トランザクションコミットするたびにファイル開いて書き込んでFlushしてるのかなー?