Frage

Ich verwende den externen Speicher zum Speichern von Ereignissen in einer Datenbank, während sie darauf warten, an den Server gesendet zu werden.

Ich sehe wirklich schlechte Leistung beim Einfügen von Datensätzen. Ich weiß, dass der externe Gedächtnis langsam sein kann, aber ich wollte eine Nummer sehen, also habe ich eine kleine App geschrieben, die sie testet.

Hier ist der Code:

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();

Die Datenbank ist genau wie die, die meine reale App verwendet. Ich habe versucht, den Index zu entfernen, aber sie machte keinen Unterschied.

Hier sind die Ergebnisse:

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 

Wie Sie sehen können, kann der Emulator nicht vertrauenswürdig sein, InsertHelper sollte schneller sein, wenn überhaupt.
Dies ist natürlich zu erwarten, dass der Test größtenteils aus Neugier durchgeführt wurde.

Was mich jedoch besorgt hat, ist die schlechte Leistung auf meinem Telefon bei der Verwendung externer Speicher? Habe ich einen entscheidenden Aspekt von verpasst? SQLiteDatabase Oder ist es einfach so, dass die SD -Karte langsam ist?

Ich kann das hinzufügen, dass ich in meiner echten App deaktiviert habe Sperren Und es macht wenig Unterschied.

War es hilfreich?

Lösung

Commonsware ist in seinem Kommentar korrekt. Etwas, das einen großen Unterschied für die DB -Leistung macht, ist die Verwendung von Transaktionen. Wickeln Sie Ihre Einsatzschleife in eine Transaktion. Ich bin mir nicht zu 100% sicher, ob es mit dem Inserthelper funktionieren würde, aber Sie können versuchen, Ihre für die Schleife durch diese zu ersetzen:

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();
}

Andere Tipps

Ich habe einige DB -Leistungsprobleme, daher habe ich Ihren Code verwendet, um die Einfügungen pro Sekunde in meinem System zu messen. Aber ich habe auch ein Verpackung in {begin, end} Transaction () hinzugefügt.

Im Emulator. Ich habe:

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

Und auf einem Samsung Galaxy Note:

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top