Ich merke, das in PyHardLinkBackup das schreiben in die SQLite Datenbank doch das ganze so aus bremst, das es quasi unbrauchbar ist, wenn es zu viele kleine Dateien sind...
Also wenn sehr oft neue Datensätze in die SQLite Datenbank in kurzer Zeit geschrieben werden...
Wie kann ich das beschleunigen?
Ich nutzte die SQLite Datenbank ja mit dem Django ORM. Vielleicht kann ich an den "transactions" was ändern: https://docs.djangoproject.com/en/1.8/t ... nsactions/
Allerdings hab ich mich bisher um Transaktionen nicht gekümmert. Ich weiß nicht, ob beim einfügen eines Datensatzes, ein "flush" ausgelöst wird?!?
Eine Idee wäre evtl. eine zweite ":memory:" SQLite Datenbank zu nutzten und von Zeit zu Zeit (oder ganz am Ende) die Daten zu kopieren. Aber das verkompliziert alles und evtl. sind Daten weg, wenn es nicht bis zum Ende durchläuft. Auf der anderen Seite, stecken in der DB keine so super wichtigen Daten. Man kann sie schnell aus dem Dateisystem wieder rekonstruieren.
Oder: Statt ":memory:" könnte ich auch die Informationen estmal nicht in die DB schreiben, sondern nur in einem normalen dict() zwischenparken. Am Ende dann in die DB packen oder von Zeit zur zeit einfügen.
Oder: Die SQLite auf einer RAM-Disk legen, wäre denkbar. Aber unter Windows nicht mal eben so machbar.
Oder: Was anderes als SQLite nehmen, geht kaum, weil der der Installationsaufwand dann viel zu hoch ist.
Hat noch jemand Ideen?
SQLite beschleunigen...
Vielleicht hilft dies hier:
Hierzu sagt auch die Doku:
Quelle: http://www.codificar.com.br/blog/sqlite ... q/#pragmasThe Boolean synchronous value controls whether or not the library will wait for disk writes to be fully written to disk before continuing. This setting can be different from the default_synchronous value loaded from the database. In typical use the library may spend a lot of time just waiting on the file system. Setting "PRAGMA synchronous=OFF" can make a major speed difference.
Hierzu sagt auch die Doku:
Quelle: http://www.sqlite.org/pragma.html#pragma_synchronous(...) some operations are as much as 50 or more times faster with synchronous OFF.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Ah! Danke für die Tips!
Hab auch noch http://www.rkblog.rk.edu.pl/w/p/sqlite- ... nd-django/ gefunden...
Weiß jemand spontan, ob das aktuell noch der Best-Practise-Weg ist:
Hab auch noch http://www.rkblog.rk.edu.pl/w/p/sqlite- ... nd-django/ gefunden...
Weiß jemand spontan, ob das aktuell noch der Best-Practise-Weg ist:
Code: Alles auswählen
from django.db.backends.signals import connection_created
def setup_sqlite(sender, connection, **kwargs):
if connection.vendor == 'sqlite':
cursor = connection.cursor()
cursor.execute('PRAGMA foo = bar;')
connection_created.connect(setup_sqlite)
@jens: Bei Django würde ich auf jeden Fall mal ansetzen denn das macht ja im Normalzustand „autocommit“, also ein Commit nach jedem einzelnen Speichern. Da könntest Du Transaktionen für Verzeichnisse machen beispielsweise, oder alle x Dateien die verarbeitet wurden. Ich weiss es jetzt nicht aus dem Kopf, aber hat Django's ORM auch eine Methode um viele Model-Exemplare gleichzeitig hinzuzufügen? Da könnte man dann nämlich auf „prepared statements“/`executemany()` auf Datenbank- beziehungsweise Datenbankmodul hoffen, was bei SQLite ein bisschen was bringen sollte.
Bei der Frage nach dem wiederherstellen der Daten aus den Dateien auf der Platte wäre ich vorsichtig, denn man muss ja auch bedenken was eigentlich passiert wenn die Datenbank korrupt ist. *Merkst* Du das denn, und wenn ja woran? Gerade bei einer Backup-Software sollte man da noch ein bisschen paranoider sein. Die taugt ja nichts wenn man ohne es zu merken mit einer fehlerhaften Datenbank weiterarbeitet und am Ende dann Sachen nicht wiederhergestellt werden können.
In dem von Dir verlinkten Blogartikel wird erwähnt das jemand auf Reddit schrieb, Transaktionen würden einen Geschwindigkeitsschub bringen. Ich würde das ja als erstes ausprobieren, bevor Du anfängst Einstellungen zu machen, die an der Datenbankintegrität kratzen könnten.
Bei der Frage nach dem wiederherstellen der Daten aus den Dateien auf der Platte wäre ich vorsichtig, denn man muss ja auch bedenken was eigentlich passiert wenn die Datenbank korrupt ist. *Merkst* Du das denn, und wenn ja woran? Gerade bei einer Backup-Software sollte man da noch ein bisschen paranoider sein. Die taugt ja nichts wenn man ohne es zu merken mit einer fehlerhaften Datenbank weiterarbeitet und am Ende dann Sachen nicht wiederhergestellt werden können.
In dem von Dir verlinkten Blogartikel wird erwähnt das jemand auf Reddit schrieb, Transaktionen würden einen Geschwindigkeitsschub bringen. Ich würde das ja als erstes ausprobieren, bevor Du anfängst Einstellungen zu machen, die an der Datenbankintegrität kratzen könnten.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Also die Datenbank spielt noch keine große Rolle: Bisher wird die ja nur genutzt um identische Dateien zu finden. Also ist der SHA512 vom Dateiinhalt vorhanden um mit os.link() einen Hardlink zu machen.BlackJack hat geschrieben:Bei der Frage nach dem wiederherstellen der Daten aus den Dateien auf der Platte wäre ich vorsichtig, denn man muss ja auch bedenken was eigentlich passiert wenn die Datenbank korrupt ist. *Merkst* Du das denn, und wenn ja woran? Gerade bei einer Backup-Software sollte man da noch ein bisschen paranoider sein. Die taugt ja nichts wenn man ohne es zu merken mit einer fehlerhaften Datenbank weiterarbeitet und am Ende dann Sachen nicht wiederhergestellt werden können.
Gut, wenn der SHA512 oder der Dateipfad manipuliert wäre, kommt murks raus. Aber nur dann, wenn es auch passt: z.B. wenn der SHA512 auf die falsche Datei zeigt.
Aber ich denke wahrscheinlicher ist, das kein os.link() gemacht wird, weil der Hash nicht zu finden ist (obwohl die Datei mit identischem Inhalt existiert) oder weil der Pfad falsch ist.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Also es gibt "bulk_create" -> https://docs.djangoproject.com/en/1.8/r ... ulk_createBlackJack hat geschrieben:Ich weiss es jetzt nicht aus dem Kopf, aber hat Django's ORM auch eine Methode um viele Model-Exemplare gleichzeitig hinzuzufügen? Da könnte man dann nämlich auf „prepared statements“/`executemany()` auf Datenbank- beziehungsweise Datenbankmodul hoffen, was bei SQLite ein bisschen was bringen sollte.
Aber das wäre keine gute Idee: So würde ich erst doppelte Einträgt finden, nachdem ein "bulk_create" gemacht wurde.
Es muß nach jedem neuen Eintragen einer Datei, diese auch direkt danach gefunden werden (Auch wenn es wohl nicht ganz so wahrscheinlich ist, das gleiche Dateien so oft hintereinander kommen werden)
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Also settings.AUTOCOMMIT=False mit "PRAGMA temp_store = MEMORY;" und "PRAGMA synchronous=OFF" scheint keinen großen Unterschied zu machen...
https://github.com/jedie/PyHardLinkBack ... c5b917a4d4
War jetzt das schnellste zum mal eben probieren...
https://github.com/jedie/PyHardLinkBack ... c5b917a4d4
War jetzt das schnellste zum mal eben probieren...
@jens
Mal ganz naiv gefragt: Wenn AUTOCOMMIT ausgeschaltet ist, benötigt die zwischengeschaltete Funktion dann nicht am Ende ein `commit()`, damit die geänderten Einstellungen auch ankommen? Hast du mal gegengeprüft, ob sich die Einstellungen für deine DB tatsächlich geändert haben?
Mal ganz naiv gefragt: Wenn AUTOCOMMIT ausgeschaltet ist, benötigt die zwischengeschaltete Funktion dann nicht am Ende ein `commit()`, damit die geänderten Einstellungen auch ankommen? Hast du mal gegengeprüft, ob sich die Einstellungen für deine DB tatsächlich geändert haben?
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Naja, die unittests laufen durch. Von daher gehe ich mal schwer von aus
Aufjeden Fall sieht man das auch mit diesen Einstellungen, fleißig die .journal Datei erzeugt und gelöscht werden... Hätte jetzt gedacht, das "PRAGMA temp_store = MEMORY;" bewirkt, das sie im RAM zwischengelagert werden...

Aufjeden Fall sieht man das auch mit diesen Einstellungen, fleißig die .journal Datei erzeugt und gelöscht werden... Hätte jetzt gedacht, das "PRAGMA temp_store = MEMORY;" bewirkt, das sie im RAM zwischengelagert werden...
@snafu: Man müsste dann wohl die Transaktionen von Django verwenden. Und natürlich nicht jede einzelne Änderung in eine Transaktion verpacken, denn dann hat man nichts gewonnen, sondern mehrere Änderungen in eine Transaktion stecken.
@jens: `temp_store` hat nichts mit dem Journal zu tun. Da gibt's auch ein Pragma für um das in den Speicher zu verlegen.
Edit: Das würde ich aber erst machen wenn Du sicher bist das Du nicht jede einzelne Änderung commitest. Wie hast Du das denn jetzt gelöst? Pro Verzeichnis oder nach x Dateien? Wie gross wäre in dem Fall x?
@jens: `temp_store` hat nichts mit dem Journal zu tun. Da gibt's auch ein Pragma für um das in den Speicher zu verlegen.
Edit: Das würde ich aber erst machen wenn Du sicher bist das Du nicht jede einzelne Änderung commitest. Wie hast Du das denn jetzt gelöst? Pro Verzeichnis oder nach x Dateien? Wie gross wäre in dem Fall x?
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Ah:
PRAGMA schema.journal_mode = MEMORY
https://www.sqlite.org/pragma.html#pragma_journal_mode
Aber:
Kann ich ja mal probieren...
Auf die schnelle das Transaktions-Verhalten zu ändern, klappte nicht.
EDIT: journal_mode = MEMORY bringt auch jeden Fall eine Beschleunigung.
PRAGMA schema.journal_mode = MEMORY
https://www.sqlite.org/pragma.html#pragma_journal_mode
Aber:
Note also that the journal_mode cannot be changed while a transaction is active.
Kann ich ja mal probieren...
Auf die schnelle das Transaktions-Verhalten zu ändern, klappte nicht.
EDIT: journal_mode = MEMORY bringt auch jeden Fall eine Beschleunigung.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Hab gesehen, das 'bedup' dieses setzt:
siehe: https://github.com/g2p/bedup/blob/7283d ... n__.py#L78
Vielleicht ist journal_mode = WAL schneller als journal_mode = MEMORY ???
Jemand Erfahrungen damit?
Code: Alles auswählen
# Uncripple the SQL implementation
cur.execute('PRAGMA foreign_keys = ON')
# So that writers do not block readers
# https://www.sqlite.org/wal.html
cur.execute('PRAGMA journal_mode = WAL')
Vielleicht ist journal_mode = WAL schneller als journal_mode = MEMORY ???
Jemand Erfahrungen damit?
@jens: WAL ist wie der Kommentar in dem Quelltext ja sagt, dafür da, dass Schreibzugriffe nicht mehr Lesezugriffe blockieren, also praktisch einsetzbar wenn viele Nutzer/Prozesse gleichzeitig auf die Datenbank zugreifen. Dafür werden mehr Dateien angelegt und ich glaube nicht das der zusätzliche Aufwand das ganze schneller macht. Das „viele Leser während des Schreibens“-Szenario hast Du doch auch gar nicht.