Schlechte Performance von SQLite, große Schreibvorgänge bringen wenig Leseaufwand

8

Verwandte Frage : How Verwenden von SQLite in einer Multithreadanwendung.

Ich habe versucht, in SQLite3 in einem Multi-Thread-Programm eine anständige Leistung zu erzielen. Abgesehen von der Schreiblatenz war ich sehr beeindruckt von der Leistung. Das ist nicht die Schuld, es muss warten, bis sich die Platte dreht, um die Daten zu übertragen. Aber während dieser Schreibvorgänge blockierte Lesevorgänge sind, selbst wenn sie aus dem Cache gelesen werden könnten, ziemlich unerträglich.

Mein Anwendungsfall beinhaltet eine große Anzahl von kleinen Leseoperationen, um ein winziges Objekt durch ein indiziertes Feld zu erhalten, aber die Latenz ist für diese Operationen wichtig, weil es viele davon gibt. Schreibvorgänge sind groß und werden in einer einzigen Transaktion zusammengefasst. Ich möchte nicht, dass die Lesevorgänge aufgrund der abgeschlossenen Schreibvorgänge eine große Latenz haben.

Ich habe zuerst nur eine einzige Verbindung mit einem Mutex verwendet, um sie zu schützen. Während der Schreib-Thread jedoch darauf wartet, dass die Transaktion abgeschlossen wird, werden die Leser auf der Datenträger-E / A blockiert, da sie den Mutex erst dann erfassen können, wenn der Verfasser sie freigibt. Ich habe versucht, mehrere Verbindungen zu verwenden, aber dann bekomme ich SQLITE_LOCKED von sqlite3_step , was bedeutet, dass ich den gesamten Lesecode neu gestalten muss.

Meine Schreiblogik sieht momentan so aus:

  1. Erhalte Verbindungs-Mutex.
  2. START TRANSACTION
  3. Schreib alles. (In der Regel 10 bis 100 kleine.)
  4. END TRANSACTION - hier blockiert es
  5. Mutex freigeben.

Gibt es eine Lösung, die mir nicht bewusst ist? Gibt es einen einfachen Weg, meine Leser davon abzuhalten, auf das Drehen der Platte zu warten, wenn sich der Eintrag im Cache befindet, ohne meinen gesamten Lesecode neu schreiben zu müssen, um SQLITE_LOCKED zu bearbeiten, zurückzusetzen und erneut zu versuchen?

    
David Schwartz 10.01.2013, 06:18
quelle

2 Antworten

6

Damit mehrere Leser und ein Schreiber gleichzeitig auf die Datenbank zugreifen können, aktivieren Sie die Protokollierung .

WAL funktioniert gut mit kleinen Transaktionen, Sie müssen also keine Schreibvorgänge ansammeln.

Bitte beachten Sie, dass WAL nicht mit vernetzten Dateisystemen funktioniert und für eine optimale Leistung regelmäßige Prüfpunkte benötigt.

    
CL. 10.01.2013, 08:01
quelle
1

Zunächst bietet sqlite Multithread-Unterstützung für sich. Sie müssen nicht Ihre eigenen Mutexe verwenden, da Sie nur das gesamte Programm verlangsamen. Konsultieren Sie sqlite thread options , wenn Sie irgendwelche Zweifel haben.

Das Verwenden des Write-Ahead-Protokolls kann Ihre Probleme lösen, aber es ist ein zweischneidiges Schwert. Solange ein Lesevorgang läuft, werden die eingefügten Daten nicht in die Hauptdatenbankdatei geschrieben und das WAL-Journal wird vergrößert. Dies wird ausführlich in Write-Ahead-Protokollierung

behandelt

Ich verwende sqlite im WAL-Modus in einer meiner Anwendungen. Bei kleinen Datenmengen funktioniert es gut. Wenn es jedoch viele Daten gibt (mehrere hundert Einfügungen pro Sekunde, in Spitzen sogar mehr), erlebe ich einige Probleme, die ich nicht durch irgendeine Einmischung in die sqlite-Konfiguration beheben kann.

Was Sie in Erwägung ziehen, ist die Verwendung mehrerer Datenbankdateien, die jeweils einer bestimmten Zeitspanne zugeordnet sind. Dies trifft nur zu, wenn Ihre Anfragen von der Zeit abhängen.

Ich laufe wahrscheinlich zu viel voraus. WAL Journal sollte helfen:)

    
Dariusz 10.01.2013 08:23
quelle

Tags und Links