PostgreSQL può scalare piuttosto bene verticalmente. Più risorse (CPU, memoria, disco) puoi mettere a disposizione del tuo server PostgreSQL, migliori saranno le sue prestazioni. Tuttavia, mentre alcune parti di Postgres possono utilizzare automaticamente le maggiori risorse, altre parti necessitano di modifiche alla configurazione prima che si possano notare miglioramenti.
Continua a leggere per saperne di più su come garantire che PostgreSQL utilizzi appieno il sistema su cui lo stai eseguendo.
CPU
Cosa scala automaticamente
PostgreSQL ha un'architettura di processo tradizionale, costituita da un processo master (chiamato postmaster ) che genera un nuovo processo (chiamato abackend ) per ogni nuova connessione client. Ciò significa che se sono disponibili più core CPU, più processi possono essere eseguiti contemporaneamente e quindi i backend non devono competere tanto per la disponibilità della CPU. Le query legate alla CPU verranno completate più rapidamente.
Potresti voler regolare le connessioni simultanee massime consentite a livello di sistema, per database o per utente:
-- system level
ALTER SYSTEM SET max_connections = 200;
-- database level
ALTER DATABASE dbname CONNECTION LIMIT 200;
-- user level
ALTER ROLE username CONNECTION LIMIT 20;
in modo che le app canaglia non possano finire per monopolizzare troppe connessioni.
Cosa deve essere modificato
Il server PostgreSQL può generare processi per occuparsi delle attività di pulizia, come l'aspirazione, la replica, gli abbonamenti (per la replica logica) ecc. Il numero di tali lavoratori non è determinato dinamicamente, ma semplicemente impostato tramite la configurazione e il valore predefinito è 8.
L'impostazione di configurazione di primo livello per il numero di processi di lavoro è:
# typically specified in postgresql.conf
max_worker_processes = 16
Aumentare questo valore può si traducono in un'accelerazione dei lavori di manutenzione, delle query parallele e della creazione di indici.
Query parallele
A partire dalla versione 9.6, Postgres può eseguire query in parallelo se il Queryplanner decide che può essere d'aiuto. L'interrogazione parallela comporta la generazione dei lavoratori, la distribuzione del lavoro tra di loro e quindi la raccolta (raccolta) dei risultati. Soggetta al limite complessivo di max_worker_processes
impostato in precedenza, Postgres determinerà quanti worker possono essere generati per query parallele in base al valore di due impostazioni di configurazione:
# 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
Se hai CPU inattive e query parallelizzabili, l'aumento di questi valori può velocizzare tali query.
Creazione di un indice parallelo
In Postgres 11 è stato aggiunto il supporto per la creazione parallela di indici B-Tree. Se crei regolarmente indici B-Tree o li REINDICE, aumentare questo valore può aiutare:
# the maximum number of parallel workers that can be
# started by a single utility command
max_parallel_maintenance_workers = 8
Ciò consentirà a Postgres di generare questi numerosi lavoratori (soggetto al limite complessivo di max_worker_processes
) per velocizzare la creazione degli indici B-Tree.
Replica logica
La replica logica (disponibile in Postgres 10 e versioni successive), si basa sui processi di lavoro sul lato dell'abbonamento per recuperare le modifiche dall'editore. Chiedendo a Postgres di generare più lavoratori di replica logica, le modifiche possono essere recuperate e applicate in parallelo, soprattutto se sono presenti più tabelle. Questa impostazione di configurazione aumenta il numero totale di lavoratori di replica:
# maximum number of logical replication workers
max_logical_replication_workers = 8
Nella replica in streaming, puoi avviare una sincronizzazione con un backup di base. Per la replica logica, tuttavia, le modifiche devono essere apportate tramite il protocollo di replica stesso, sulla rete. Questo può richiedere molto tempo. Consentire a più lavoratori durante la fase di sincronizzazione può accelerare questo processo:
# basically the number of tables that are synced in
# parallel during initialization of subscription
max_sync_workers_per_subscription = 8
Autovacuum
Periodicamente, sulla base di una serie di impostazioni di configurazione, Postgres genererà un mucchio di lavoratori che Aspireranno le tabelle del database. Questo è ovviamente chiamato autovacuum, e il numero di lavoratori che l'autovacuum launcher genera ogni volta può essere impostato tramite l'impostazione di configurazione:
# the maximum number of autovacuum processes
autovacuum_max_workers = 8
Compressione WAL
Se hai CPU di riserva, puoi barattare la CPU con la larghezza di banda del disco comprimendo le pagine che sono scritte nei file WAL. Ciò riduce la quantità di dati che devono essere scritti su disco, a scapito di più cicli della CPU per comprimere i dati. Riduce anche la dimensione dei dati che devono essere inviati attraverso il cavo per la replica in streaming.
In pratica, i vantaggi della compressione WAL valgono molto il ragionevoleoverhead. Per attivarlo, usa:
# compresses full page images written to WAL
wal_compression = on
Memoria
Cosa scala automaticamente
Il sistema operativo gestisce e utilizza automaticamente la memoria non utilizzata da alcuna applicazione per memorizzare nella cache i dati letti e scritti di recente sul disco. Ciò velocizza notevolmente le applicazioni ad alta intensità di disco e sicuramente PostgreSQL.
In Linux, l'host più popolare per Postgres, la dimensione della cache del disco del sistema operativo non può essere impostata dall'utente. La sua gestione è interna a Linux. Sotto la pressione della memoria, cederà la memoria cache del disco alle applicazioni.
Cosa deve essere modificato
Pianificatore query
Il pianificatore di query deve includere la quantità di cache del disco fornita dal sistema operativo come fattore nelle sue stime. Se sei riuscito ad aumentare significativamente la cache del disco del sistema operativo (aumentando la memoria disponibile), l'aumento di questa impostazione di configurazione potrebbe aiutare a migliorare le stime del pianificatore:
# the planner's assumption about the effective size
# of the disk cache that is available to a single query.
effective_cache_size = 64GB
Memoria condivisa
PostgreSQL utilizza una serie di buffer condivisi tra tutti i lavoratori e i processi di backend. Questi sono chiamati buffer condivisi e la quantità di memoria allocata per i buffer condivisi viene impostata utilizzando l'impostazione di configurazione:
shared_buffers = 32GB
Buffer temporanei
Quando si accede a tabelle temporanee da una query, i buffer vengono allocati per memorizzare nella cache il contenuto che viene letto. La dimensione di questo buffer viene impostata utilizzando l'impostazione di configurazione:
# the maximum number of temporary buffers used
# by each database session
temp_buffers = 100MB
Se hai memoria da risparmiare e query che utilizzano molto tabelle temporanee, l'aumento di questo valore può velocizzare tali query.
Memoria di lavoro
La memoria di lavoro è allocata localmente e privatamente dai backend. Viene utilizzato per eseguire ordinamenti e join senza dover creare tabelle temporanee. Aumentando questo valore rispetto al valore predefinito di 4 MB, le query vengono completate più rapidamente durante la creazione di tabelle temporanee:
# the amount of memory to be used by internal sort
# operations and hash tables before writing to temporary disk files
work_mem = 16MB
Operazioni di manutenzione
La memoria utilizzata da VACUUM, creazione dell'indice e altri comandi di manutenzione simili sono controllati dall'impostazione di configurazione maintenance_work_mem
. L'aumento di questo importo può velocizzare queste operazioni, in particolare su indici o tabelle che devono essere ricreati.
La memoria utilizzata dagli operatori autovacuum può essere prelevata dalla memoria di lavoro di manutenzione (impostando autovacuum_work_mem = -1
) o configurati in modo indipendente.
# 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
Disco
Cosa scala automaticamente
I dischi possono essere più grandi, più veloci o più simultanei. La dimensione del disco è l'unica cosa su cui PostgreSQL non deve essere istruito. Per impostazione predefinita, PostgreSQL non si limiterà a utilizzare lo spazio su disco disponibile. Di solito va bene.
Tuttavia, puoi porre un limite alla dimensione totale dei file temporanei creati, per fornire una certa protezione contro le query che tentano di ordinare un miliardo di righe e simili:
# the maximum amount of disk space that a process
# can use for temporary files
temp_file_limit = 500GB
Cosa deve essere modificato
Concorrenza
I dischi RAID e i file system come ZFS possono essere configurati per supportare più concorrenza. Vale a dire, è possibile che alcune letture/scritture del disco vengano gestite contemporaneamente da tali file system a causa del modo in cui vengono archiviati o gestiti i dati internamente.
Puoi consentire a Postgres di emettere più I/O simultanei del disco, utilizzando questa impostazione di configurazione:
# the number of concurrent disk I/O operations that
# PostgreSQL expects can be executed simultaneously
effective_io_concurrency = 4
Tuttavia, questo è attualmente utilizzato solo dalle scansioni dell'heap bitmap.
Costo della pagina casuale
Il pianificatore di query di Postgres presuppone che le letture sequenziali siano più veloci delle letture casuali. Esattamente quanto più veloce è un valore che puoi modificare. Per impostazione predefinita, presuppone che le letture casuali siano 4 volte più costose.
A seconda della configurazione del disco, del carico di lavoro e del benchmarking, se sei sicuro che le letture casuali siano, ad esempio, solo due volte più costose delle letture sequenziali, puoi dirlo a Postgres:
# 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
Tablespace
Per sfruttare più dischi che non sono montati come un unico grande filesystem, puoi usare i tablespace. Con i tablespace, puoi posizionare tabelle o indicizzare diversi filesystem. Ciò può migliorare la concorrenza e fornisce un modo semplice per gestire la crescita della tabella.
CREATE TABLESPACE disk2 LOCATION '/mnt/disk2/postgres';
Leggi di più sui tablespace qui.
Rete
La rete è solitamente la risorsa meno utilizzata su un server PostgreSQL e raramente è saturata. Se è necessario ridimensionare, è abbastanza facile aggiungere più interfacce di rete, ciascuna con il proprio IP e fare in modo che PostreSQL le ascolti tutte:
listen_addresses = '10.1.0.10,10.1.0.11'
I client dovranno essere bilanciati nel carico su tutti gli IP su cui Postgres ascolta.
Altro
Ci sono alcune altre impostazioni di configurazione che possono essere modificate, la maggior parte delle quali consuma più CPU e memoria.
Operazioni partizionate
Postgres 10 ha introdotto il partizionamento delle tabelle, che è stato migliorato in Postgres 11. Alcune ottimizzazioni delle query sulle partizioni non sono attivate per impostazione predefinita, poiché potrebbero comportare un maggiore consumo di CPU e memoria. Questi sono:
# 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