pg_prewarm ist eine Extension zum Laden von Tabellenblöcken in den Betriebssystem oder PostgreSQL Buffer Cache. Dabei wird die Ausführung entweder manuell über das Ausführen einer Funktion oder automatisch per Konfigurationseintrag in der postgresql.conf mit dem Parameter shared_preload_libraries gesteuert. Im zweiten Fall läuft ein worker Prozess bei der PostgreSQL Instanz mit und speichert regelmäßig den Inhalt der Shared Buffers in der Datei $PGDATA/autoprewarm.blocks. Im Falle eines Neustarts der Instanz laden zwei background worker alle in der Datei hinterlegten Blöcke erneut in die Shared Buffers.

Die Extension enthält noch zwei Konfigurationsparameter für die pospg_prewarm.autoprewarm (boolean): Ermöglicht das das An-/Abschalten von pg_prewarm ohne das Einträge aus der postgresql.conf entfernt werden müssen. Der Standardwert ist “on” und der Parameter kann nur beim Serverstart gesetzt werden.

  • pg_prewarm.autoprewarm_interval (int): Intervall der Updates der autoprewarm.blocks Datei in Sekunden. Der Standardwert sind 300 Sekunden. Beim Einstellen des Werts 0 wird nur beim Herunterfahren der PostgreSQL Instanz ein Dump erzeugt.

Wenn die Extension im laufenden Betrieb des Datenbankclusters aktiviert wurde, bieten die Funktionen autoprewarm_start_worker(), das nachträgliche Starten des background worker Prozesses, sowie autoprewarm_dump_now() das Aktualisieren der autoprewarm.blocks Datei.

Zuletzt kann die Aufnahme von Tabellen und deren Blöcken auch über die Funktion pg_prewarm(…) gesteuert werden:

Copy to Clipboard
  • regclass: Name der Tabelle
  • mode: Es gibt 3 unterschiedliche Ladestrategien

– prefetch: Asynchrones Laden per Betriebssystemaufruf

– read: Liest die Liste der definierten Datenblöcke und lädt im Gegensatz zu prefetch synchron, aber eventuell langsamer

– buffer: Liest die Datenblöcke in den Datenbank Buffer Cache

  • fork: Normalerweise main für die Hauptdatendatei
  • first_block: Erster zu lesender Block, NULL synonym für 0, also Beginn der Tabelle
  • last_block: Letzter zu lesender Block, NULL bis Ende der Tabelle

Anmerkung: Mehr Informationen zu dem Parameter fork und seiner Bedeutung ist in der Postgres Dokumentation zu finden.

Zum Testen wird docker-compose mit Postgres v12 verwendet. In einem ersten Test wird dabei pg_prewarm nicht verwendet.

Copy to Clipboard

Der Container wird mit docker-compose gestartet und danach wird sich per docker exec auf den Container geschaltet.

Copy to Clipboard

Nun wird eine Datenbank testdb erzeugt und pgbench initialisiert. Dabei ist die Skalierung so gewählt, dass die Datenbank komplett in die Shared Buffers geladen werden kann.

Copy to Clipboard

Der eigentliche Test kann jetzt beginnen. Dazu wird der Container gestoppt, erneut gestartet und in den Container verbunden.

Copy to Clipboard

Per pgbench werden die TPS ermittelt. Es wird ein Client simuliert, der 10 Minuten lang nur selects ausführt. pgbench gibt den Fortschritt inklusive TPS-Wert alle 5 Sekunden aus. Dieser wird in die Logdatei pgbench.log geschrieben.

Copy to Clipboard

Als nächstes wird die docker-compose Datei um pg_prewarm als Startparameter erweitert.

Copy to Clipboard

Der Container wird gestartet.

Copy to Clipboard

Als erstes lässt sich der zu Beginn beschriebene Prozess zu pg_prewarm anzeigen.

Copy to Clipboard

Wie bei dem ersten Container wird die Datenbank testdb erzeugt und danach pg_prewarm aktiviert. Die pgbench Tabellen werden explizit geladen und anschließend mit autoprewarm_dump_now gedumpt.

Copy to Clipboard

Der eigentliche Test kann jetzt beginnen. Dazu wird der Container gestoppt, erneut gestartet und mit dem Container verbunden.

Copy to Clipboard
Vergleich der TPS Werte

Abbildung: Vergleich der TPS Werte

Beim Vergleich der TPS Werte ohne und mit pg_prewarm zeigen sich zu Beginn der Aufzeichnungen deutliche Unterschiede. Ohne pg_prewarm dauert es fast 2 Minuten lang bis die TPS Werte ein ähnliches Niveau wie mit pg_prewarm erreichen. Das liegt daran, dass die Data Pages erst bei Abfrage aus dem Dateisystem in den PostgreSQL Buffer Cache geladen werden. Daraus ist zu schließen, dass pg_prewarm bei (sehr) großen Datenbankclustern mit viel RAM einen deutlichen Vorteil bringt.

Die Extension hilft so bei unterschiedlichsten Anwendungsfällen. Dazu gehört an erster Stelle die bessere Reaktionszeit auf User-Anfragen nach einem Neustart des Datenbankclusters. Auf der anderen Seite kann pg_prewarm auch bei Tests genutzt werden, um authentische Zustände im Buffer Cache zu generieren, wie sie auch in Produktion zu finden sind.

Blog Dirk Aumüller

Dirk Aumüller

Dirk Aumueller arbeitet als Associate Partner für die Proventa AG. Sein technologischer Schwerpunkt liegt bei Datenbankarchitekturen mit PostgreSQL sowie Data Management Lösungen mit Pentaho. Zusätzlich zu seinen Datenbanktransformations-Projekteinsätzen ist er regelmäßig als PostgreSQL Trainer unterwegs und betreut Studenten bei ihren Abschlussarbeiten. Seine fachlichen Erfahrungen erstrecken sich über die Branchen Telco und Financial Services.