Postgresql. Kann Update-Abfrage parallel ausgeführt werden?

8

Ich habe einen großen Tisch mit 10m Reihen. Und ich muss für jede Zeile einen statistischen Wert erhalten. Ich habe eine Funktion, die diesen Wert erzeugt, zum Beispiel GetStatistic(uuid) . Diese Funktion arbeitet sehr langsam und der Wert des Ergebnisses ändert sich nicht oft. Deshalb habe ich die Spalte Statistic in meiner Tabelle erstellt und führe einmal am Tag eine Abfrage wie diese aus:

%Vor%

Und in ausgewählten Abfragen verwende ich die Spalte Statistic ohne Aufruf von GetStatistic functions.

Problem ist, dass mein Produktionsserver 64 CPUs und viel Speicher hat, so dass fast alle DB im RAM zwischengespeichert werden können, aber diese Abfrage verwendet nur eine CPU und benötigt 2 oder 3 Stunden zur Ausführung.

GetStatistic-Funktion Verwendungstabelle, die während der Ausführung der UPDATE-Abfrage konstant ist. Kann ich die Abfrage ändern, um postgre zu erhalten, um GetStatistic parallel für verschiedene Zeilen gleichzeitig zu berechnen, wobei alle verfügbaren CPUs verwendet werden?

    
Yavanosta 17.10.2012, 09:16
quelle

1 Antwort

9

PostgreSQL führt jede Abfrage in einem einzigen Backend aus, bei dem es sich um einen Prozess mit einem einzelnen Thread handelt. Es kann nicht mehr als eine CPU für eine Abfrage verwenden. Es ist auch etwas eingeschränkt, was E / A-Parallelität innerhalb einer einzelnen Abfrage erreichen kann, wirklich nur simultane I / O für Bitmap-Index-Scans und ansonsten auf dem Betriebssystem und Disk-System für gleichzeitige E / A.

Pg ist gut, wenn viele kleinere Abfragen gleichzeitig ausgeführt werden, und es ist einfach, Ihr System auf diese Weise zu sättigen. Es ist einfach nicht so gut, die besten Systemressourcen für eine oder zwei wirklich große Abfragen bereitzustellen.

Sie können den Job in Stücke aufteilen und an die Arbeiter verteilen. Sie haben darauf hingewiesen mit:

  

Kann ich die Abfrage ändern, um postgre zu erhalten, um GetStatistic parallel zu berechnen   für verschiedene Zeilen gleichzeitig mit allen verfügbaren CPUs?

Es gibt eine Vielzahl von Tools, wie DBlink , PL/Proxy , pgbouncer und < a href="http://www.pgpool.net/"> PgPool-II , die dazu bestimmt sind, bei dieser Art von Arbeit zu helfen. Alternativ können Sie es auch selbst tun, indem Sie (zum Beispiel) 8 Worker starten, die sich jeweils mit der Datenbank verbinden und UPDATE ... WHERE id BETWEEN ? AND ? -Anweisungen mit nicht überlappenden ID-Bereichen ausführen. Eine ausgefeiltere Option besteht darin, dass ein Warteschlangen-Controller Bereiche von ungefähr 1000 IDs an Arbeiter verteilt, die UPDATE diesen Bereich dann nach einem neuen fragen.

Beachten Sie, dass 64 CPUs nicht bedeutet, dass 64 gleichzeitige Arbeiter ideal sind. Ihre Festplatten-E / A ist auch ein Faktor, wenn es um Schreibvorgänge geht. Sie können Ihren E / A-Kosten ein wenig helfen, wenn Sie Ihre UPDATE -Transaktionen auf commit_delay setzen und (falls Ihre Geschäftsanforderungen für diese Daten sicher sind) synchronous_commit = 'off' , dann sollte das Laden von Synchronisationen erheblich reduziert werden. Nichtsdestoweniger ist es wahrscheinlich, dass der beste Durchsatz weit unter 64 gleichzeitig arbeitenden Mitarbeitern erreicht wird.

Es ist sehr wahrscheinlich, dass Ihre GetStatistic -Funktion sehr viel schneller gemacht werden kann, indem Sie sie in eine inlineable SQL-Funktion oder -Ansicht umwandeln, und nicht, was vermutlich eine schleifenlastige prozedurale PL / pgSQL-Funktion ist. Es könnte hilfreich sein, wenn Sie diese Funktion angezeigt haben.

    
Craig Ringer 17.10.2012, 12:17
quelle