Androidの外部ストレージでの悪いSQLiteパフォーマンス
-
28-10-2019 - |
質問
イベントがサーバーに送信されるのを待っている間に、データベースにイベントを保存するために外部ストレージを使用しています。
レコードを挿入するとき、私は本当に悪いパフォーマンスを見ています。外部メモリが遅くなる可能性があることはわかっていますが、いくつかを見たかったので、テストする小さなアプリを書きました。
これがコードです:
public static final int INSERTS = 100;
File dbFile = new File(Environment.getExternalStorageDirectory(), "test.sqlite3");
// File dbFile = new File(getFilesDir(), "test.sqlite3");
dbFile.delete();
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbFile, null);
db.execSQL("CREATE TABLE events (_id integer primary key autoincrement, event_type TEXT NOT NULL, timestamp BIGINT, data TEXT);");
db.execSQL("CREATE INDEX mainIndex ON events (event_type, timestamp ASC);");
InsertHelper helper = new InsertHelper(db, "events");
final int eventTypeCol = helper.getColumnIndex("event_type");
final int timestampCol = helper.getColumnIndex("timestamp");
final int dataCol = helper.getColumnIndex("data");
long start = System.currentTimeMillis();
String eventType = "foo", data = "bar";
long timestamp = 4711;
for(int i = 0; i < INSERTS; ++i) {
helper.prepareForInsert();
helper.bind(eventTypeCol, eventType);
helper.bind(timestampCol, timestamp);
helper.bind(dataCol, data);
helper.execute();
}
long end = System.currentTimeMillis();
Log.i("Test", String.format("InsertHelper, Speed: %d ms, Records per second: %.2f", (int)(end-start), 1000*(double)INSERTS/(double)(end-start)));
db.close();
dbFile.delete();
db = SQLiteDatabase.openOrCreateDatabase(dbFile, null);
db.execSQL("CREATE TABLE events (_id integer primary key autoincrement, event_type TEXT NOT NULL, timestamp BIGINT, data TEXT);");
db.execSQL("CREATE INDEX mainIndex ON events (event_type, timestamp ASC);");
start = System.currentTimeMillis();
ContentValues cv = new ContentValues();
for(int i = 0; i < INSERTS; ++i) {
cv.put("event_type", eventType);
cv.put("timestamp", timestamp);
cv.put("data", data);
db.insert("events", null, cv);
}
end = System.currentTimeMillis();
Log.i("Test", String.format("Normal, Speed: %d ms, Records per second: %.2f", end-start, 1000*(double)INSERTS/(double)(end-start)));
db.close();
dbFile.delete();
データベースは、実際のアプリが使用しているものとまったく同じです。インデックスを削除しようとしましたが、違いはありませんでした。
ここに結果があります:
Nexus One, Internal memory Method | Records | Time (ms) | Records per second -------------+---------+-----------+-------------------- Normal | 100 | 2072 | 48.26 InsertHelper | 100 | 1662 | 60.17 Nexus One, External memory: Method | Records | Time (ms) | Records per second -------------+---------+-----------+-------------------- Normal | 100 | 7390 | 13.53 InsertHelper | 100 | 7152 | 13.98 Emulator, Internal memory: Method | Records | Time (ms) | Records per second -------------+---------+-----------+-------------------- Normal | 100 | 1803 | 55.46 InsertHelper | 100 | 3075 | 32.52 Emulator, External memory: Method | Records | Time (ms) | Records per second -------------+---------+-----------+-------------------- Normal | 100 | 5742 | 17.42 InsertHelper | 100 | 7164 | 13.96
あなたが見ることができるように、エミュレータを信頼することはできません、 InsertHelper
どちらかといえば、より速くなるはずです。
もちろん、これは予想されることですが、テストはほとんどが好奇心から行われました。
しかし、私が心配しているのは、外部メモリを使用するときの携帯電話のパフォーマンスが悪いことです。 SQLiteDatabase
それとも、SDカードが遅くなるように単純にですか?
私はそれを私の本当のアプリに追加することができます私は無効になっています ロック そして、それはほとんど違いをもたらします。
解決
コモンズウェアは彼のコメントで正しいです。 DBパフォーマンスに大きな違いをもたらすものは、トランザクションを使用することです。インサートループをトランザクションに包みます。 InserThelperと一緒に機能するかどうかは100%確信していませんが、これにループを交換してみることができます。
db.beginTransaction();
try {
for(int i = 0; i < INSERTS; ++i) {
helper.prepareForInsert();
helper.bind(eventTypeCol, eventType);
helper.bind(timestampCol, timestamp);
helper.bind(dataCol, data);
helper.execute();
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
他のヒント
私にはいくつかのDBパフォーマンスの問題があるので、あなたのコードを使用して、システムの1秒あたりの挿入物を測定しました。しかし、{begin、end} transaction()にラッピングも追加しました。
エミュレータで。手に入れた:
InsertHelper-Internal-Trans, Speed: 67 ms, Records per second: 1492.54
InsertHelper-External-Trans, Speed: 70 ms, Records per second: 1428.57
Normal-Internal-Trans, Speed: 148 ms, Records per second: 675.68
Normal-External-Trans, Speed: 152 ms, Records per second: 657.89
InsertHelper-Internal-NoTrans, Speed: 514 ms, Records per second: 194.55
Normal-Internal-NoTrans, Speed: 519 ms, Records per second: 192.68
InsertHelper-External-NoTrans, Speed: 590 ms, Records per second: 169.49
Normal-External-NoTrans, Speed: 618 ms, Records per second: 161.81
そして、サムスンギャラクシー注:
InsertHelper-External-Trans, Speed: 52 ms, Records per second: 1923.08
InsertHelper-Internal-Trans, Speed: 52 ms, Records per second: 1923.08
Normal-External-Trans, Speed: 77 ms, Records per second: 1298.70
Normal-Internal-Trans, Speed: 121 ms, Records per second: 826.45
Normal-External-NoTrans, Speed: 4562 ms, Records per second: 21.92
Normal-Internal-NoTrans, Speed: 4855 ms, Records per second: 20.60
InsertHelper-External-NoTrans, Speed: 5997 ms, Records per second: 16.68
InsertHelper-Internal-NoTrans, Speed: 8361 ms, Records per second: 11.96