Edited at

Android: SQLiteインサート高速化で、パフォーマンスのイライラを解消する

More than 3 years have passed since last update.


AndroidのSQLiteでバルクインサートする方法です。


普通にインサートする時


通常のインサート処理

DatabaseHelper dbHelper = new DataBaseHelper();

SQLiteDatabase db = new dbHelper.getWritableDatabase();

//インサートするデータのArrayList
List<ContentValues> valueList = new ArrayList<ContentValues>();

//データ作成
ContentValues values = new ContentValues();
values.put("Name", "hoge");
values.put("Tel", "0000-1234-5678");
values.put("Age", 24);
valueList.add(values);
values = new ContentValues();
values.put("Name", "fuga");
values.put("Tel", "0000-1234-5678");
values.put("Age", 30);
valueList.add(values);

for (ContentValues val : valueList) {
long ret = db.insert("MyTable", null, val);
if (ret < 0) {
Log.d("ログのタグ", "インサート失敗!!!!!");
}
}
db.close();


このようにArrayListをLoopで回して1件ずつインサートすると、SQLiteは1件ずつインサートするごとに

トランザクションのコミットを行います。

少量のデータのインサートなら1件ずつトランザクションコミットが走ることは気になりませんが、

大量データとなると、コミットのコストはバカになりません。

そこで、データを全部インサートしたあとに、コミットを行うことで、トランザクションコミットのコストを最小限にすることができます。


バルクインサートする時


バルクインサート処理

// トランザクション開始を宣言

db.beginTransaction();
try {
for (ContentValues val : valueList) {
long ret = db.insert("MyTable", null, val);
if (ret < 0) {
Log.d("ログのタグ", "インサート失敗!!!!!");
}
}
//トランザクション成功を宣言。
db.setTransactionSuccessful();

} finally {
// トランザクション終了
db.endTransaction();
db.close();
}


このように明示的にトランザクションの開始、成功、終了を宣言することで、トランザクションコミットのタイミングをコントロールすることができます。

setTransactionSuccessful()を呼び出すことで、データベースへの変更がコミットされ、呼び出さなければロールバックされます

そのためこの方法には、以下のメリットがあります。


  • 高速化

  • 途中で失敗した場合ロールバックができる


パフォーマンス比較

以下のサイトに比較があったので、貼っつけておきます。約2倍ほど高速です。


http://www.atmarkit.co.jp/ait/articles/0905/20/news111_2.html


1.PNG