it-swarm.com.de

Postgres beschleunigt die Indexerstellung für große Tabellen

Ich habe eine große Postgres-Tabelle mit 2+ Milliarden Einträgen (1,5 TB) und meistens nicht null, char var-Spalten. Um das Einfügen zu beschleunigen, habe ich die Indizes vor dem Massen-Upload gelöscht. Es dauert jedoch ewig, bis die B-Tree-Indizes erstellt sind. Bei einem der Läufe, die ich abgebrochen habe, wurden mehr als 12 Stunden für die Erstellung der Indizes aufgewendet.

Beispieltabelle und Indizes, die ich erstellen möchte:

        Column         |            Type             | Modifiers 
-----------------------+-----------------------------+-----------
 name                  | character varying           | not null
 id                    | character varying           | 
 lifecycle_id          | character varying           | 
 dt                    | character varying           | 
 address               | character varying           | 
 ...

Indexes: 
"name_idx" PRIMARY KEY, btree (name)

"id_idx" btree (rec_id)

"lifecycle_id_idx" btree (lifecycle_id)

Die aktuelle Tabelle enthält 18 Spalten. Ich habe dastenance_work_mem auf 15 GB festgelegt. Dies läuft auf Postgres 9.6.11 auf RDS. Die Instanzklasse ist db.m4.4xlarge.

Da es drei Indizes gibt, ist es schwierig, die Daten vor dem Einfügen zu sortieren. Wäre es schneller, nur die Daten einzufügen, ohne die Indizes zu löschen? Irgendwelche anderen Vorschläge zur Beschleunigung der Indexerstellung?

3
Amy

PostgreSQL hat die Möglichkeit hinzugefügt, einen einzelnen Index in Version 10 zu parallelisieren, sodass Sie ein Upgrade in Betracht ziehen können, um diese Funktion nutzen zu können.

Selbst in der Version, die Sie derzeit verwenden, können Sie mehrere Indizes für dieselbe Tabelle gleichzeitig erstellen (indem Sie unterschiedliche Datenbankverbindungen verwenden, um jede einzelne aufzurufen), sodass Sie immer noch einen gewissen Grad an informeller Parallelisierung erhalten. Sie können dies nur mit regulären Indexerstellungen tun, die Änderungen an der Tabelle während der Indexerstellung sperren. Mit der Indexerstellung "gleichzeitig" kann UPDATE/INSERT/DELETE gleichzeitig mit der Indexerstellung ausgeführt werden. Indexerstellungen für dieselbe Tabelle dürfen jedoch nicht gleichzeitig ausgeführt werden.

Nach meiner Erfahrung sind die virtuellen CPUs von AWS praktisch unbrauchbar. Während db.m4.4xlarge 16 vCPU meldet, macht es keinen Sinn, über 8 hinaus zu parallelisieren. Wenn Sie Parallelität verwenden möchten (entweder v10-Einzelindex oder nur mehrere Indizes gleichzeitig erstellen), benötigen Sie wahrscheinlich einen kleineren Wert für wartung_arbeit_mem als 15GB.

Wäre es schneller, nur die Daten einzufügen, ohne die Indizes zu löschen?

Irgendwann definitiv. Es hängt davon ab, wie viele Datensätze sich in Ihren Bulk-Beilagen befinden, sowie von einer Reihe anderer Dinge, und kann nicht einfach durch Nachdenken beantwortet werden. Es ist eine experimentelle Frage.

3
jjanes

Die beste Optimierungsmethode zum Erstellen von Indizes ist ein sehr hoher Wert für maintenance_work_mem.

Wenn Sie einer 1,5 TB -Tabelle) nur ein paar Millionen Zeilen hinzufügen, ist das Löschen und Neuerstellen der Indizes wahrscheinlich langsamer. Sie müssen Tests ausführen, um den Punkt zu bestimmen, an dem sie schneller werden.

3
Laurenz Albe

Bevor ich diese Frage stellte, liefen zwei Tests, aber ich war mir nicht sicher, ob sie jemals beendet werden würden. Ich hatte gehofft, einen Einblick zu bekommen, wie ich es beschleunigen kann, wenn sie nie fertig sind. Zum Glück wurde einer der Tests beendet. Ich habe auch gute Ergebnisse erzielt, indem ich die Vorschläge ausprobiert habe, die jjanes gepostet hat.

Mit Postgres 9 habe ich zwei Tests durchgeführt:

  • Einfügen der 2 Milliarden Einträge mit Indizes
  • Erstellen von Indizes für eine Tabelle, in die bereits 2 Milliarden Einträge eingefügt wurden

Der erste Test läuft seit einer Woche und hat nur 20% der 2 Milliarden Einträge eingefügt. Das Einfügen mit Index ist definitiv nicht der richtige Weg.

Der zweite Test dauerte 45 Stunden. Ohne zu wissen, wie lange die Indexerstellung dauern würde, habe ich einige der vorherigen Tests vorzeitig abgebrochen und sie nie vollständig gesehen. Es dauert lange, aber im Moment bin ich froh, dass es nicht für immer läuft.

Unter Berücksichtigung der Vorschläge von jjanes habe ich ein Upgrade auf Postgres 11 durchgeführt, die parallelen Worker auf 8 und den Wartungsarbeitsspeicher auf 7 GB festgelegt. Ich habe diese Anleitung befolgt, um die Parameter auszuwählen: https://www.cybertec-postgresql.com/de/postgresql-parallel-create-index-for-better-performance/ . Dies beschleunigte die Indexerstellung und dauerte nur 35 Stunden. 10 Stunden zu rasieren war eine schöne Überraschung. Vielen Dank!

3
Amy