PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

So beschleunigen Sie die Einfügeleistung in PostgreSQL

Siehe Befüllen einer Datenbank im PostgreSQL-Handbuch, den wie gewohnt ausgezeichneten Artikel von depesz zu diesem Thema und diese SO-Frage.

(Beachten Sie, dass es in dieser Antwort um das Massenladen von Daten in eine vorhandene DB oder um das Erstellen einer neuen geht. Wenn Sie interessiert sind, stellen Sie die Leistung der DB mit pg_restore wieder her oder psql Ausführung von pg_dump Ausgabe, vieles davon gilt seit pg_dump nicht mehr und pg_restore bereits Dinge wie das Erstellen von Triggern und Indizes, nachdem eine Schema- und Datenwiederherstellung abgeschlossen ist) .

Es gibt viel zu tun. Die ideale Lösung wäre der Import in ein UNLOGGED Tabelle ohne Indizes, ändern Sie sie dann in protokolliert und fügen Sie die Indizes hinzu. Leider gibt es in PostgreSQL 9.4 keine Unterstützung für das Ändern von Tabellen von UNLOGGED zu protokollieren. 9.5 fügt ALTER TABLE ... SET LOGGED hinzu um Ihnen dies zu ermöglichen.

Wenn Sie Ihre Datenbank für den Massenimport offline schalten können, verwenden Sie pg_bulkload .

Ansonsten:

  • Alle Trigger in der Tabelle deaktivieren

  • Löschen Sie Indizes, bevor Sie den Import starten, und erstellen Sie sie anschließend neu. (Es braucht viel weniger Zeit, um einen Index in einem Durchgang zu erstellen, als dieselben Daten nach und nach hinzuzufügen, und der resultierende Index ist viel kompakter).

  • Wenn Sie den Import innerhalb einer einzigen Transaktion durchführen, ist es sicher, Fremdschlüsseleinschränkungen zu löschen, den Import durchzuführen und die Einschränkungen vor dem Festschreiben neu zu erstellen. Tun Sie dies nicht, wenn der Import auf mehrere Transaktionen aufgeteilt ist, da Sie möglicherweise ungültige Daten einführen.

  • Verwenden Sie nach Möglichkeit COPY statt INSERT s

  • Wenn Sie COPY nicht verwenden können erwägen Sie die Verwendung von mehrwertigem INSERT s wenn praktisch. Du scheinst das schon zu tun. Versuchen Sie nicht, auch aufzulisten viele Werte in einem einzigen VALUES obwohl; diese Werte müssen mehrmals in den Speicher passen, also halten Sie es bei ein paar hundert pro Anweisung.

  • Stapeln Sie Ihre Einfügungen in explizite Transaktionen und führen Sie Hunderttausende oder Millionen von Einfügungen pro Transaktion durch. Es gibt kein praktisches Limit AFAIK, aber die Stapelverarbeitung ermöglicht es Ihnen, einen Fehler zu beheben, indem Sie den Beginn jedes Stapels in Ihren Eingabedaten markieren. Auch hier scheinen Sie dies bereits zu tun.

  • Verwenden Sie synchronous_commit=off und eine riesige commit_delay fsync()-Kosten zu reduzieren. Dies hilft jedoch nicht viel, wenn Sie Ihre Arbeit in großen Transaktionen zusammengefasst haben.

  • INSERT oder COPY parallel von mehreren Anschlüssen. Wie viele hängt vom Disk-Subsystem Ihrer Hardware ab; Als Faustregel gilt, dass Sie eine Verbindung pro physischer Festplatte benötigen, wenn Sie Direct Attached Storage verwenden.

  • Legen Sie eine hohe max_wal_size fest Wert (checkpoint_segments in älteren Versionen) und aktivieren Sie log_checkpoints . Sehen Sie sich die PostgreSQL-Protokolle an und vergewissern Sie sich, dass es sich nicht über zu häufig auftretende Checkpoints beschwert.

  • Wenn und nur wenn es Ihnen nichts ausmacht, Ihren gesamten PostgreSQL-Cluster (Ihre Datenbank und alle anderen auf demselben Cluster) durch katastrophale Beschädigung zu verlieren, wenn das System während des Imports abstürzt, können Sie Pg stoppen und fsync=off , starte Pg, führe deinen Import durch, stoppe dann (unbedingt) Pg und setze fsync=on wieder. Siehe WAL-Konfiguration. Tun Sie dies nicht, wenn es bereits Daten, die Sie interessieren, in einer Datenbank Ihrer PostgreSQL-Installation gibt. Wenn Sie fsync=off setzen Sie können auch full_page_writes=off setzen; Denken Sie auch hier daran, es nach dem Import wieder einzuschalten, um eine Beschädigung der Datenbank und Datenverlust zu vermeiden. Siehe nicht dauerhafte Einstellungen im Pg-Handbuch.

Sie sollten sich auch mit der Optimierung Ihres Systems befassen:

  • Verwenden Sie gute Qualität SSDs für die Speicherung so viel wie möglich. Gute SSDs mit zuverlässigen, stromgeschützten Write-Back-Caches machen Commit-Raten unglaublich schneller. Sie sind weniger vorteilhaft, wenn Sie die obigen Ratschläge befolgen - was Festplattenspülungen / Anzahl von fsync() reduziert s - kann aber trotzdem eine große Hilfe sein. Verwenden Sie keine billigen SSDs ohne angemessenen Stromausfallschutz, es sei denn, Sie kümmern sich nicht um die Aufbewahrung Ihrer Daten.

  • Wenn Sie RAID 5 oder RAID 6 für direkt angeschlossenen Speicher verwenden, hören Sie jetzt auf. Sichern Sie Ihre Daten, strukturieren Sie Ihr RAID-Array auf RAID 10 um und versuchen Sie es erneut. RAID 5/6 sind für Massenschreibleistung hoffnungslos - obwohl ein guter RAID-Controller mit einem großen Cache helfen kann.

  • Wenn Sie die Möglichkeit haben, einen Hardware-RAID-Controller mit einem großen batteriegestützten Write-Back-Cache zu verwenden, kann dies die Schreibleistung für Workloads mit vielen Commits wirklich verbessern. Es hilft nicht so viel, wenn Sie einen asynchronen Commit mit einem commit_delay verwenden oder wenn Sie während des Massenladens weniger große Transaktionen durchführen.

  • Speichern Sie nach Möglichkeit WAL (pg_wal , oder pg_xlog in alten Versionen) auf einer separaten Festplatte / einem Festplattenarray. Es macht wenig Sinn, ein separates Dateisystem auf derselben Festplatte zu verwenden. Die Leute entscheiden sich oft dafür, ein RAID1-Paar für WAL zu verwenden. Auch dies wirkt sich stärker auf Systeme mit hohen Commit-Raten aus und hat nur geringe Auswirkungen, wenn Sie eine nicht protokollierte Tabelle als Datenladeziel verwenden.

Sie könnten auch daran interessiert sein, PostgreSQL für schnelles Testen zu optimieren.