Massenimport: Performance optimieren

Hallo liebes Forum,

ich portiere gerade eine Anwendung von sqlite3 zu Postgresql. Grund: Netzwerkfähigkeit und Zugriff von vielen Klienten auf dieselben Daten.
Es gibt Datenbanken mit 10Mio+ Einträgen welche ich importieren muss. Das dauert leider mit einer Verbindung relativ lange. In meinem Testfall 30 Minuten für 5 Mio Einträge. Jetzt hab ich 48 Threads gemacht welche parallel die Daten importieren. Ein Sqlite3 “Producer” und 48 Verbindungen um sie zu importieren. Die Importer schreiben “nicht normalisiert” in eine Import Tabelle und dann wird zyklisch das “normalisiert” und in die Zieltabellen geschrieben.

Gibt es eine einfachere aber trotzdem effektive Methode das zu importieren? Kann man den “Durchsatz” einer Verbindung noch erhöhen?

Momentan mit den 48 Threads schaut das so aus:

Meine Umgebung:

  • Debian Linux (Bookworm)
  • Postgresql 15.7 (PostgreSQL 15.7-git on x86_64-pc-linux-gnu, compiled by gcc (GCC) 14.1.0, 64-bit)
  • libpqxx 7.9.1 (git Version)
  • gcc-14.1 (git Version)

Transaction Isolation Level musste ich auf
using Transaction_t = pqxx::transaction<pqxx::isolation_level::serializable>;
setzen da die Prozedur zum verschieben der importierten Daten ein Delete ohne Bedingung auf der Import Tabelle macht und dabei noch nicht verschobene Daten gelöscht worden sind. Der direkte Import hat deutlich länger gebraucht da er häufiger JOINs gebraucht hat als der jetztige Ansatz.

Für Ideen wäre ich dankbar! :slight_smile:

Viele Grüße
Georg

Sehe ich da richtig: 8000 Transaktionen pro Sekunde? Wenn jede Zeile eine eigene Datenbanktransaktion ist, wird klar, warum das so langsam ist.

Ok, dann sollte ich die Anzahl der Zeilen erhöhen die pro Transaktion geschrieben werden. Danke dir :slight_smile:

Am besten importiert man die ganze Datenbank in einer einzigen Transaktion.

1 „Gefällt mir“

10 Millionen Datensätze sollten eigentlich keine aufwändigen “parallelen Imports” benötigen. Zumindest das Schreiben in die Importtabelle sollte mit einem COPY Befehl nicht länger als “wenige Minuten” dauern.

Ohne den Code zu kennen, wird es schwierig da irgendwelche Tips zu geben. Bei der Weiterverarbeitung innerhalb der Datenbank ist es im Regelfall effizienter, wenn man das alles mit einem Statement macht (INSERT ... ON CONFLICT oder MERGE). Häufig sind FOR Schleifen die jeden Datensatz einzeln lesen, ändern und schreiben ein Grund für geringen Durchsatz.