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

PostgreSQL vertikal skalieren

PostgreSQL kann recht gut vertikal skalieren. Je mehr Ressourcen (CPU, Arbeitsspeicher, Festplatte) Sie Ihrem PostgreSQL-Server zur Verfügung stellen können, desto besser kann er arbeiten. Während jedoch einige Teile von Postgres die erhöhten Ressourcen automatisch nutzen können, müssen andere Teile an der Konfiguration geändert werden, bevor Verbesserungen bemerkt werden können.

Lesen Sie weiter, um mehr darüber zu erfahren, wie Sie sicherstellen können, dass PostgreSQL das System, auf dem Sie es ausführen, vollständig nutzt.

Prozessor

Was automatisch skaliert

PostgreSQL hat eine traditionelle Prozessarchitektur, bestehend aus einem Masterprozess (genannt postmaster ), der einen neuen Prozess (als Backend bezeichnet) erzeugt ) für jede neue Clientverbindung. Das bedeutet, wenn mehr CPU-Kerne verfügbar sind, können mehr Prozesse gleichzeitig laufen und Backends müssen daher nicht so sehr um die CPU-Verfügbarkeit kämpfen. CPU-gebundene Abfragen werden schneller abgeschlossen.

Möglicherweise möchten Sie die maximal zulässigen gleichzeitigen Verbindungen systemweit, pro Datenbank oder pro Benutzer anpassen:

-- system level
ALTER SYSTEM SET max_connections = 200;

-- database level
ALTER DATABASE dbname CONNECTION LIMIT 200;

-- user level
ALTER ROLE username CONNECTION LIMIT 20;

damit betrügerische Apps nicht zu viele Verbindungen in Beschlag nehmen können.

Was angepasst werden muss

Der PostgreSQL-Server kann Prozesse erzeugen, die Verwaltungsaufgaben erledigen, wie z. B. Bereinigung, Replikation, Abonnements (für logische Replikation) usw. Die Anzahl solcher Worker wird nicht dynamisch bestimmt, sondern einfach über die Konfiguration festgelegt und ist standardmäßig 8.

Die Konfigurationseinstellung der obersten Ebene für die Anzahl der Worker-Prozesse lautet:

# typically specified in postgresql.conf
max_worker_processes = 16

Das Erhöhen dieses Werts kann führen zu einer Beschleunigung von Wartungsaufträgen, parallelen Abfragen und der Indexerstellung.

Parallele Abfragen

Ab Version 9.6 kann Postgres Abfragen parallel ausführen, wenn der Abfrageplaner entscheidet, dass dies hilfreich ist. Parallele Abfragen beinhalten das Spawnen von Workern, das Verteilen der Arbeit unter ihnen und das anschließende Sammeln (Sammeln) der Ergebnisse. Vorbehaltlich der Gesamtbeschränkung von max_worker_processes zuvor festgelegt, bestimmt Postgres, wie viele Worker für parallele Abfragen erzeugt werden können, abhängig vom Wert zweier Konfigurationseinstellungen:

# the maximum number of workers that the system can
# support for parallel operations
max_parallel_workers = 8

# the maximum number of workers that can be started
# by a single Gather or Gather Merge node
max_parallel_workers_per_gather = 8

Wenn Sie CPUs im Leerlauf und parallelisierbare Abfragen haben, können Sie diese Abfragen beschleunigen, indem Sie diese Werte erhöhen.

Parallele Indexerstellung

In Postgres 11 wurde die Unterstützung für die parallele Erstellung von B-Tree-Indizes hinzugefügt. Wenn Sie regelmäßig B-Tree-Indizes erstellen oder diese REINDEXEN, kann es hilfreich sein, diesen Wert zu erhöhen:

# the maximum number of parallel workers that can be
# started by a single utility command
max_parallel_maintenance_workers = 8

Dadurch kann Postgres diese vielen Worker erstellen (vorbehaltlich des Gesamtlimits von max_worker_processes ), um die Erstellung von B-Tree-Indizes zu beschleunigen.

Logische Replikation

Die logische Replikation (verfügbar in Postgres 10 und höher) stützt sich auf Arbeitsprozesse auf der Abonnementseite, um Änderungen vom Herausgeber abzurufen. Indem Sie Postgres auffordern, mehr logische Replikations-Worker zu erstellen, können die Änderungen abgerufen und parallel angewendet werden, insbesondere wenn mehr Tabellen vorhanden sind. Diese Konfigurationseinstellung erhöht die Gesamtzahl der Replication Worker:

# maximum number of logical replication workers
max_logical_replication_workers = 8

Bei der Streaming-Replikation können Sie eine Synchronisierung mit einer Basissicherung starten. Für die logische Replikation müssen Änderungen jedoch über das Replikationsprotokoll selbst über das Netzwerk eingezogen werden. Dies kann zeitaufwändig sein. Das Zulassen weiterer Worker während der Synchronisierungsphase kann diesen Vorgang beschleunigen:

# basically the number of tables that are synced in
# parallel during initialization of subscription
max_sync_workers_per_subscription = 8

Selbstvakuum

Basierend auf einer Reihe von Konfigurationseinstellungen wird Postgres in regelmäßigen Abständen eine Reihe von Workern hervorbringen, die die Datenbanktabellen VAKUUMIEREN. Dies wird natürlich als Autovacuum bezeichnet, und die Anzahl der Worker, die der Autovacuum Launcher jedes Mal spawnt, kann über die Konfigurationseinstellung festgelegt werden:

# the maximum number of autovacuum processes
autovacuum_max_workers = 8

WAL-Komprimierung

Wenn Sie CPU übrig haben, können Sie die CPU gegen Festplattenbandbreite eintauschen, indem Sie die Seiten komprimieren, die in die WAL-Dateien geschrieben werden. Dies reduziert die Datenmenge, die auf die Platte geschrieben werden muss, auf Kosten von mehr CPU-Zyklen zum Komprimieren der Daten. Es reduziert auch die Größe der Daten, die für die Streaming-Replikation über das Kabel gesendet werden müssen.

In der Praxis sind die Vorteile der WAL-Komprimierung den sehr günstigen Mehraufwand wert. Verwenden Sie zum Einschalten:

# compresses full page images written to WAL
wal_compression = on

Speicher

Was automatisch skaliert

Das Betriebssystem verwaltet und verwendet automatisch Speicher, der von keiner Anwendung zum Zwischenspeichern von Daten verwendet wird, die kürzlich von der Festplatte gelesen und auf diese geschrieben wurden. Dadurch werden plattenintensive Anwendungen und insbesondere PostgreSQL erheblich beschleunigt.

In Linux, dem beliebtesten Host für Postgres, kann die Größe des Betriebssystem-Festplattencaches nicht vom Benutzer festgelegt werden. Die Verwaltung erfolgt intern in Linux. Unter Speicherdruck gibt es Festplatten-Cache-Speicher für Anwendungen frei.

Was angepasst werden muss

Abfrageplaner

Der Abfrageplaner muss die vom Betriebssystem bereitgestellte Menge an Festplatten-Cache als Faktor in seine Schätzungen einbeziehen. Wenn es Ihnen gelungen ist, den Festplattencache des Betriebssystems erheblich zu erhöhen (indem Sie den verfügbaren Speicher erhöht haben), kann eine Erhöhung dieser Konfigurationseinstellung zur Verbesserung der Schätzungen des Planers beitragen:

# the planner's assumption about the effective size
# of the disk cache that is available to a single query.
effective_cache_size = 64GB

Gemeinsamer Speicher

PostgreSQL verwendet eine Reihe von Puffern, die von allen Workern und Backend-Prozessen gemeinsam genutzt werden. Diese werden als gemeinsame Puffer bezeichnet , und die Menge an Speicher, die gemeinsam genutzten Puffern zugewiesen wird, wird mit der Konfigurationseinstellung festgelegt:

shared_buffers = 32GB

Temporäre Puffer

Wenn durch eine Abfrage auf temporäre Tabellen zugegriffen wird, werden Puffer zugewiesen, um den eingelesenen Inhalt zwischenzuspeichern. Die Größe dieses Puffers wird mit der Konfigurationseinstellung festgelegt:

# the maximum number of temporary buffers used
# by each database session
temp_buffers = 100MB

Wenn Sie Speicher übrig haben und Abfragen stark temporäre Tabellen verwenden, kann das Erhöhen dieses Werts solche Abfragen beschleunigen.

Arbeitsgedächtnis

Arbeitsspeicher wird lokal und privat von Backends zugewiesen. Es wird verwendet, um Sortierungen und Verknüpfungen durchzuführen, ohne temporäre Tabellen erstellen zu müssen. Wenn Sie dies von der Standardeinstellung von 4 MB erhöhen, können Abfragen schneller abgeschlossen werden, indem während der Erstellung temporärer Tabellen:

# the amount of memory to be used by internal sort
# operations and hash tables before writing to temporary disk files
work_mem = 16MB

Wartungsvorgänge

Der Speicher, der von VACUUM, der Indexerstellung und anderen solchen Wartungsbefehlen verwendet wird, wird durch die Konfigurationseinstellung maintenance_work_mem gesteuert . Eine Erhöhung dieses Betrags kann diese Vorgänge beschleunigen, insbesondere bei Indizes oder Tabellen, die neu erstellt werden müssen.

Der von den Autovacuum-Workern verwendete Speicher kann dem Wartungsarbeitsspeicher entnommen werden (durch Setzen von autovacuum_work_mem = -1 ) oder unabhängig konfiguriert werden.

# the maximum amount of memory to be used by
# maintenance operations
maintenance_work_mem = 128MB

# maximum amount of memory to be used by each
# autovacuum worker process
autovacuum_work_mem = -1

Datenträger

Was automatisch skaliert

Festplatten können größer, schneller oder gleichzeitiger gemacht werden. Die Größe der Platte ist das einzige, was PostgreSQL nicht mitgeteilt werden muss. Standardmäßig beschränkt sich PostgreSQL nicht darauf, verfügbaren Speicherplatz zu verwenden. Dies ist normalerweise in Ordnung.

Sie können jedoch die Gesamtgröße der erstellten temporären Dateien begrenzen, um einen gewissen Schutz vor Abfragen zu bieten, die versuchen, eine Milliarde Zeilen und dergleichen zu sortieren:

# the maximum amount of disk space that a process
# can use for temporary files
temp_file_limit = 500GB

Was angepasst werden muss

Gleichzeitigkeit

RAID-fähige Festplatten und Dateisysteme wie ZFS können so eingerichtet werden, dass sie mehr Parallelität unterstützen. Das heißt, Sie können aufgrund der Art und Weise, wie Daten intern gespeichert oder verarbeitet werden, einige Lese-/Schreibvorgänge auf der Festplatte gleichzeitig von solchen Dateisystemen ausführen lassen.

Sie können Postgres mehrere gleichzeitige Datenträger-E/A ausgeben lassen, indem Sie diese Konfigurationseinstellung verwenden:

# the number of concurrent disk I/O operations that
# PostgreSQL expects can be executed simultaneously
effective_io_concurrency = 4

Dies wird derzeit jedoch nur von Bitmap-Heap-Scans verwendet.

Zufällige Seitenkosten

Der Postgres-Abfrageplaner geht davon aus, dass sequentielle Lesevorgänge schneller sind als zufällige Lesevorgänge. Wie viel schneller ist genau ein Wert, den Sie optimieren können. Standardmäßig wird davon ausgegangen, dass zufällige Lesevorgänge viermal teurer sind.

Wenn Sie sicher sind, dass zufällige Lesevorgänge beispielsweise nur doppelt so teuer sind wie sequenzielle Lesevorgänge, können Sie dies je nach Festplattenkonfiguration, Arbeitslast und Benchmarking Postgres mitteilen:

# the planner's estimate of the cost of a disk page
# fetch that is part of a series of sequential fetches
seq_page_cost = 1

# the planner's estimate of the cost of a
# non-sequentially-fetched disk page
random_page_cost = 2

Tablespaces

Um mehrere Festplatten zu nutzen, die nicht als ein einziges großes Dateisystem gemountet sind, können Sie Tablespaces verwenden. Mit Tablespaces können Sie Tabellen platzieren oder verschiedene Dateisysteme indizieren. Dies kann die Parallelität verbessern und bietet eine einfache Möglichkeit, das Tabellenwachstum zu handhaben.

CREATE TABLESPACE disk2 LOCATION '/mnt/disk2/postgres';

Lesen Sie hier mehr über Tablespaces.

Netzwerk

Das Netzwerk ist normalerweise die am wenigsten genutzte Ressource auf einem PostgreSQL-Server und ist selten ausgelastet. Wenn Sie skalieren müssen, ist es einfach genug, weitere Netzwerkschnittstellen mit jeweils eigener IP hinzuzufügen und PostreSQL auf allen lauschen zu lassen:

listen_addresses = '10.1.0.10,10.1.0.11'

Die Clients müssen über alle IPs verteilt werden, auf denen Postgres zuhört.

Andere

Es gibt ein paar andere Konfigurationseinstellungen, die angepasst werden können, von denen die meisten mehr CPU und verbrauchen Speicher.

Partitionsbezogene Operationen

Mit Postgres 10 wurde die Tabellenpartitionierung eingeführt, die in Postgres 11 verbessert wurde. Einige Abfrageoptimierungen für Partitionen sind standardmäßig nicht aktiviert, da sie zu einer höheren CPU- und Speicherauslastung führen können. Diese sind:

# allow a join between partitioned tables to be
# performed by joining the matching partitions
enable_partitionwise_join = on

# allow grouping or aggregation on a partitioned
# tables performed separately for each partition
enable_partitionwise_aggregate = on