Performanceprobleme bei INSERT in SqliteDB

  • 8 Antworten
  • Letztes Antwortdatum
F

Flixius

Fortgeschrittenes Mitglied
4
Hallo liebe Gemeinde!

wenn ich in meine SqliteDB in der App Datensätze inserte, dann dauert es "extrem" lange. Insgesamt habe ich 2200 Datensätze und dafür brauche ich auf dem Nexus S im Release Build 90-120 Sekunden.

Das Objekt hat 19 Propertys wovon die meisten int sind. Ein paar Strings sind auch dabei, aber sie sind noch viel länger als 50 Zeichen. Ob ich in der SqliteDB den Datentyp text oder nvarchar angebe hat keine Aufwirkung auf die Performance.

Pro Datensatz wird ein ganz einfaches insert ohne joins oder ähnlichen Aktionen gemacht. Die Tabelle hat ein Int als PK.

Ich kann mir nicht vorstellen, dass solch eine schlechte Performance normal ist, denn 2200 Datensätze sind ja nun wirklich nicht besonders viel.

Hier ein Codesnippet des Teils, der so lange dauert:

Code:
PlayerDAO playerDao = new PlayerDAO(ctx);
                playerDao.open();
                for(Player p : players)
                    playerDao.InsertNewPlayer(p);
                 playerDao.close();

Die Klasse PlayerDao:
Code:
public class PlayerDAO {

    private SQLiteDatabase database;
    private MySQLiteHelper dbHelper;

public PlayerDAO(Context context) {
        dbHelper = new MySQLiteHelper(context);
    }

public void open() throws SQLException {
        database = dbHelper.getWritableDatabase();
    }

public void InsertNewPlayer(Player p) {
        database.insert(MySQLiteHelper.TABLE_Player, null,p.GetContentValuesForSqlite());    
    }
}

SqliteHelper:

Code:
public class MySQLiteHelper extends SQLiteOpenHelper {
public MySQLiteHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
//etc..
}

Ich hoffe jemand kann mir helfen. Mein gesamtes App Konzept ist jetzt kurz vor Fertigstellung dadurch auf den Kopf gestellt worden, da es die gesamte Abruflogik über den Haufen wirft. Alles über 10 Sekunden wird problematisch denke ich. Das Nexus S ist zwar nicht gerade das schnellste Handy, aber wenn ich mir überlege, dass die App auch auf 2.1 läuft, wird mir ganz anders zumute. :(
 
brauchst keine angst haben :)

bau eine transaktion drum herum und es wird 80-90 % schneller laufen
 
  • Danke
Reaktionen: Flixius
ich kenne das Performanceproblem auch,

beginTransaction();
setTransactionSuccessful();
und
endTransaction();

bringen im Emulator auf die Schnelle jetzt
aber keine Unterschiede. :unsure:
 
  • Danke
Reaktionen: Flixius
dann machst du etwas falsch

edit: ich teste aber nie im emulator ...
 
jetzt mit Gerät:

auf 80-90% komme ich zwar nicht - aber ... :thumbup:

Es hängt sehr stark von der Tabellenstruktur ab.

Eine Tabelle mit 2 INT-Spalten

2924 Records - mit Transaction : 14sec - ohne Transaktion: 93sec

Eine Tabelle mit 2 INT-Spalten und 3 TEXT-Spalten

800 Records - mit Transaction : 10sec - ohne Transaktion: 32sec

Eine Tabelle mit 6 INT-Spalten und 12 TEXT-Spalten

1051 Records - mit Transaction : 40sec - ohne Transaktion: 70sec


Alle Inserts wurden mit Hilfe
compileStatement, bindString und execute vorbereitet/ausgeführt

Teilweise wurden vorher noch Strings manipuliert in der Schleife.

Das macht die Sache sicherlich schwer vergleichbar. Wie sah deine

Tabelle aus bei der Du wie gesagt 80-90% Geschwindigkeitsvorteil

erfahren hast ? Sicherlich waren da auch keine weiteren Operationen

in der Schleife, wie bei mir.
 
Text und varchar sind für Datenbanken schwer zu handhaben, da sie diese (wegen der veränderlichen Größe) in der Regel separat und nicht einfach mit der restlichen Zeile ablegen.
Hier wäre zu überlegen, ob du nicht auf char mit festen Größen umsteigen kannst. Zusätzliche Leerzeichen heraus zu trimmen, ist ja eigentlich unproblematisch - du musst dann aber mit einer entsprechend größeren Datenbank rechnen - je nachdem wie stark deine tatsächlichen Werte (bei varchar) von der max. Länge (bei char) abweichen.


EDIT: Versuch auch mal, (vielleicht in 100er Schritten) erst die einzelnen Insert-Statements zu einem großen zusammenzufassen (mit ";" trennen) und das dann einmal auszuführen (also statt 100x1 Insert machst du 1x100 Inserts). Das bringt dir auf richtig großen Servern einiges an Performance-Schub - evtl. ist das hier auch so. Indirekt deckst das aber schon mit der Transaktion ab - wäre aber dennoch einen Versuch wert, denke ich.
 
Zuletzt bearbeitet:
naja ob das jetzt 80-90% waren oder 70-80 oder was weiß ich. das sollte nur verdeutlichen, dass es mit transaktionen um einiges schneller geht.
 
okay, das tut es ja auch :thumbup:
 
Thyrion schrieb:
EDIT: Versuch auch mal, (vielleicht in 100er Schritten) erst die einzelnen Insert-Statements zu einem großen zusammenzufassen (mit ";" trennen) und das dann einmal auszuführen (also statt 100x1 Insert machst du 1x100 Inserts). Das bringt dir auf richtig großen Servern einiges an Performance-Schub - evtl. ist das hier auch so. Indirekt deckst das aber schon mit der Transaktion ab - wäre aber dennoch einen Versuch wert, denke ich.

das funktioniert aber nur, wenn man es als rawQuery raus schickt, oder?

ich habe jetzt mithilfe der transaktion schon mal einen deutlichen performanceschub bekommen. jetzt dauert es auf dem handy nur noch 2,5 sekunden die daten zu inserten. ist blöd, dass ich natürlich nicht weiß in wieweit die ladezeiten bei anderen geräten in die höhe schnellen und von daher würde ich gerne noch mal so viel perofrmance wie möglich einsparen.

wichtiger hinweis für alle, die ihre performance der db testen wollen: führt die applikation NICHT im debugmodus aus. damit erhöhen sich die ladezeiten enorm!
 
Zurück
Oben Unten