Le prestazioni ottimali di PostgreSQL dipendono dalla corretta definizione dei parametri del sistema operativo. Parametri del kernel del sistema operativo mal configurati possono portare a una riduzione delle prestazioni del server del database. È quindi fondamentale che questi parametri siano configurati in base al server del database e al suo carico di lavoro. In questo post discuteremo alcuni parametri importanti del kernel di Linux che possono influenzare le prestazioni del server del database e i modi per configurarli.
SHMMAX / SHMALL
SHMMAX è un parametro del kernel utilizzato per definire la dimensione massima di un singolo segmento di memoria condivisa (shared memory) che può essere allocato da un processo Linux. Fino alla versione 9.2, PostgreSQL utilizzava System V (SysV), per il quale è necessaria la configurazione di SHMMAX. Dopo la 9.2, PostgreSQL è passato alla memoria condivisa POSIX. Pertanto, ora sono necessari meno byte di memoria condivisa System V.
Fino alla versione 9.3, SHMMAX era il parametro del kernel più importante. Il valore di SHMMAX è specificato in byte.
Allo stesso modo, SHMALL è un altro parametro del kernel utilizzato per definire
il volume totale di pagine di memoria condivisa (shared memory). Per visualizzare i valori attuali di SHMMAX, SHMALL o SHMMIN, utilizzare il comando ipcs.
Dettagli SHM* — Linux
$ ipcs -lm
------ Limiti della memoria condivisa --------
numero massimo di segmenti = 4096
max seg size (kbytes) = 1073741824
max total shared memory (kbytes) = 17179869184
min seg size (bytes) = 1Dettagli SHM* — MacOS X
$ ipcs -M
Stato IPC da a giovedì 16 agosto 22:20:35 PKT 2018
shminfo:
shmmax: 16777216 (dimensione massima del segmento di memoria condivisa)
shmmin: 1 (dimensione minima del segmento di memoria condivisa)
shmmni: 32 (numero massimo di identificatori di memoria condivisa)
shmseg: 8 (segmenti di memoria condivisa massimi per processo)
shmall: 1024 (importo massimo della memoria condivisa in pagine)
PostgreSQL utilizza System V IPC per allocare memoria condivisa. Questo parametro è uno dei più importanti del kernel. Ogni volta che ricevi i seguenti messaggi di errore, significa che hai una versione precedente di PostgreSQL e un valore SHMMAX molto basso. Ci si aspetta che gli utenti correggano e aumentino il valore in base alla memoria condivisa che intendono utilizzare.
Possibili errori di configurazione errata
Se SHMMAX è configurato in modo errato, puoi ricevere un errore quando tenti di inizializzare un cluster PostgreSQL utilizzando il comando initdb.
Errore di initdb
DETTAGLIO: La chiamata di sistema fallita era shmget(key=1, size=2072576, 03600).
SUGGERIMENTO: Questo errore di solito significa che la richiesta di PostgreSQL per un segmento di memoria condivisa ha superato il parametro SHMMAX del tuo kernel.
Puoi ridurre la dimensione della richiesta o riconfigurare il kernel con un SHMMAX più grande. Per ridurre la dimensione della richiesta (attualmente 2072576 byte),
riduci l'uso della memoria condivisa di PostgreSQL, magari riducendo shared_buffers o max_connections.
Se la dimensione della richiesta è già ridotta, è possibile che sia inferiore al parametro SHMMIN del tuo kernel,
nel qual caso è necessario aumentare la dimensione della richiesta o riconfigurare SHMMIN.
La documentazione di PostgreSQL contiene ulteriori informazioni sulla configurazione della memoria condivisa. Il processo figlio è terminato con codice di uscita 1
In modo simile, puoi ottenere un errore al momento dell'avvio del server PostgreSQL utilizzando il comando pg_ctl.
Errore pg_ctl
DETTAGLIO: La chiamata di sistema fallita è stata shmget(key=5432001, size=14385152, 03600).
SUGGERIMENTO: Questo errore di solito significa che la richiesta di PostgreSQL per un segmento di memoria condivisa ha superato il parametro SHMMAX del tuo kernel.
Puoi ridurre la dimensione della richiesta o riconfigurare il kernel con un SHMMAX più grande.; Per ridurre la dimensione della richiesta (attualmente 14385152 byte), riduci l'uso della memoria condivisa di PostgreSQL, magari riducendo shared_buffers o max_connections.
Se la dimensione della richiesta è già ridotta, è possibile che sia inferiore al parametro SHMMIN del tuo kernel,
nel qual caso è necessario aumentare la dimensione della richiesta o riconfigurare SHMMIN.
La documentazione di PostgreSQL contiene ulteriori informazioni sulla configurazione della memoria condivisa.
Comprensione delle differenze nelle definizioni
La definizione dei parametri SHMMAX/SHMALL è leggermente diversa in Linux e MacOS X:
- Linux: kernel.shmmax, kernel.shmall
- MacOS X: kern.sysv.shmmax, kern.sysv.shmall
Team sysctl può essere utilizzata per modificare temporaneamente il valore. Per impostare valori permanenti, aggiungi una voce in /etc/sysctl.conf. Maggiori dettagli sono forniti di seguito.
Modifica dei parametri del kernel su MacOS X
# Get the value of SHMMAX
sudo sysctl kern.sysv.shmmax
kern.sysv.shmmax: 4096
# Get the value of SHMALL
sudo sysctl kern.sysv.shmall
kern.sysv.shmall: 4096
# Set the value of SHMMAX
sudo sysctl -w kern.sysv.shmmax=16777216
kern.sysv.shmmax: 4096 -> 16777216
# Set the value of SHMALL
sudo sysctl -w kern.sysv.shmall=16777216
kern.sysv.shmall: 4096 -> 16777216Modifica dei parametri del kernel su Linux
# Get the value of SHMMAX
sudo sysctl kernel.shmmax
kernel.shmmax: 4096
# Get the value of SHMALL
sudo sysctl kernel.shmall
kernel.shmall: 4096
# Set the value of SHMMAX
sudo sysctl -w kernel.shmmax=16777216
kernel.shmmax: 4096 -> 16777216
# Set the value of SHMALL
sudo sysctl -w kernel.shmall=16777216
kernel.shmall: 4096 -> 16777216Non dimenticare di: per rendere le modifiche permanenti, aggiungi questi valori in /etc/sysctl.conf
Pagine grandi (Huge Pages)
In Linux, per impostazione predefinita, vengono utilizzate pagine di memoria da 4 KB, in BSD — Super Pages, e in Windows — Large Pages. Una pagina è una parte della memoria volatile assegnata a un processo. Un processo può avere più pagine a seconda delle esigenze di memoria. Più memoria richiede un processo, più pagine gli vengono assegnate. Il sistema operativo supporta una tabella di assegnazione delle pagine per i processi. Minore è la dimensione della pagina, più grande è la tabella, maggiore è il tempo richiesto per cercare la pagina in questa tabella delle pagine. Pertanto, le pagine grandi consentono di utilizzare una grande quantità di memoria con una minore sovraccarico; meno accessi alle pagine, meno errori di pagina, operazioni di lettura/scrittura più veloci tramite buffer più grandi. Di conseguenza, si ottimizza le prestazioni.
PostgreSQL supporta le pagine grandi solo su Linux. Per impostazione predefinita, Linux utilizza pagine di memoria di 4 KB, quindi nei casi in cui ci siano troppe operazioni di memoria, è necessario impostare pagine di dimensioni maggiori. Si osserva un aumento delle prestazioni utilizzando pagine grandi di dimensione 2 MB fino a 1 GB. La dimensione della pagina grande può essere impostata durante l'avvio. Puoi facilmente controllare i parametri delle pagine grandi e il loro utilizzo sul tuo computer Linux usando il comando cat /proc/meminfo | grep -i huge.
Ottenere informazioni sulle pagine grandi (solo su Linux)
Nota: questo è solo per Linux, per altri sistemi operativi quest'operazione è ignorata$ cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kBIn questo esempio, anche se la dimensione della pagina grande è impostata a 2048 (2 MB), il numero totale di pagine grandi è 0. Questo significa che le pagine grandi sono disabilitate.
Script per determinare il numero di pagine grandi
Questo semplice script restituisce il numero necessario di pagine grandi. Esegui lo script sul tuo server Linux mentre PostgreSQL è in esecuzione. Assicurati che la variabile d'ambiente $PGDATA sia impostata sulla directory dei dati di PostgreSQL.
Ottenere il numero di pagine grandi richieste
#!/bin/bash
pid=`head -1 $PGDATA/postmaster.pid`
echo "Pid: $pid"
peak=`grep ^VmPeak /proc/$pid/status | awk '{ print $2 }'`
echo "VmPeak: $peak kB"
hps=`grep ^Hugepagesize /proc/meminfo | awk '{ print $2 }'`
echo "Hugepagesize: $hps kB"
hp=$((peak/hps))
echo Set Huge Pages: $hpL'output dello script appare come segue:
Output dello script
Pid: 12737
VmPeak: 180932 kB
Hugepagesize: 2048 kB
Set Huge Pages: 88Il valore raccomandato delle pagine grandi è 88, quindi dovresti impostare il valore a 88.
Impostazione delle pagine grandi
sysctl -w vm.nr_hugepages=88Controlla le pagine grandi ora, vedrai che non vengono utilizzate (HugePages_Free = HugePages_Total).
Di nuovo informazioni sulle pagine grandi (solo su Linux)
$ cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 88
HugePages_Free: 88
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kBOra imposta il parametro huge_pages «on» in $PGDATA/postgresql.conf e riavvia il server.
E di nuovo informazioni sulle pagine grandi (solo su Linux)
$ cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 88
HugePages_Free: 81
HugePages_Rsvd: 64
HugePages_Surp: 0
Hugepagesize: 2048 kBOra puoi vedere che vengono utilizzate molto poche pagine grandi. Proviamo ora ad aggiungere alcuni dati al database.
Alcune operazioni con il database per l'utilizzo delle grandi pagine
postgres=# CREATE TABLE foo(a INTEGER);
CREATE TABLE
postgres=# INSERT INTO foo VALUES(generate_Series(1,10000000));
INSERT 0 10000000Diamo un'occhiata se stiamo utilizzando più grandi pagine ora rispetto a prima.
Ancora una volta, informazioni sulle grandi pagine (solo su Linux)
$ cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 88
HugePages_Free: 18
HugePages_Rsvd: 1
HugePages_Surp: 0
Hugepagesize: 2048 kBOra puoi vedere che la maggior parte delle grandi pagine vengono utilizzate.
Nota: il valore approssimativo per HugePages utilizzato qui è molto basso, il che non è normale per una macchina in produzione. Si prega di valutare il numero necessario di pagine per il proprio sistema e impostarle di conseguenza in base al carico e alle risorse.
vm.swappiness
vm.swappiness è un altro parametro del kernel che può influenzare le prestazioni del database. Questo parametro viene utilizzato per gestire il comportamento di swap (swappiness) (trasferimento delle pagine in memoria e viceversa) in Linux. Il valore varia da 0 a 100. Definisce quanta memoria verrà scaricata o scambiata. Zero significa disattivare lo scambio, mentre 100 significa uno scambio aggressivo.
Puoi ottenere buone prestazioni impostando valori più bassi.
Impostare il valore 0 nei kernel più recenti può portare OOM Killer (il processo di pulizia della memoria in Linux) a terminare il processo. Pertanto, è possibile impostare in modo sicuro un valore di 1 se si desidera minimizzare lo swapping. Il valore predefinito in Linux è 60. Un valore più alto fa sì che l'MMU (modulo di gestione della memoria) utilizzi più spazio di swap rispetto alla RAM, mentre un valore più basso conserva più dati/codice in memoria.
Un valore più basso è una buona scommessa per migliorare le prestazioni in PostgreSQL.
vm.overcommit_memory / vm.overcommit_ratio
Le applicazioni ricevono memoria e la rilasciano quando non è più necessaria. Ma in alcuni casi, un'applicazione riceve troppa memoria e non la rilascia. Questo può attivare l'OOM killer. Ecco i possibili valori del parametro vm.overcommit_memory con una descrizione per ciascuno:
- Overcommit euristico (predefinito); euristica basata sul kernel
- Consentire l'overcommit in ogni caso
- Non esagerare, non superare il coefficiente di overcommit.
Link:
vm.overcommit_ratio — percentuale di memoria RAM disponibile per il sovraccarico eccessivo. Un valore del 50% in un sistema con 2 GB di RAM può allocare fino a 3 GB di RAM.
Il valore 2 per vm.overcommit_memory garantisce migliori prestazioni per PostgreSQL. Questo valore massimizza l'utilizzo della memoria RAM da parte del processo server senza significativi rischi di essere terminato dal processo OOM killer. L'applicazione potrà riavviarsi, ma solo nei limiti del sovraccarico, riducendo il rischio che l'OOM killer uccida il processo. Pertanto, il valore 2 offre prestazioni migliori rispetto al valore predefinito 0. Tuttavia, l'affidabilità può essere migliorata evitando il sovraccarico della memoria oltre il range consentito. Questo elimina il rischio di terminazione del processo da parte dell'OOM killer.
Nei sistemi senza swap puede esserci un problema con vm.overcommit_memory impostato a 2.
vm.dirty_background_ratio / vm.dirty_background_bytes
vm.dirty_background_ratio — è la percentuale di memoria occupata da pagine sporche che devono essere scritte su disco. Il salvataggio su disco avviene in background. Il valore di questo parametro oscilla tra 0 e 100; tuttavia, un valore inferiore a 5 può essere inefficace e alcuni kernel non lo supportano. 10 è il valore predefinito nella maggior parte dei sistemi Linux. Puoi migliorare le prestazioni per le operazioni di scrittura intensiva con un fattore più basso, il che significa che Linux salverà le pagine sporche in background.
Devi impostare il valore vm.dirty_background_bytes in base alla velocità del tuo disco.
Per questi due parametri non ci sono valori "buoni", poiché entrambi dipendono dall'hardware. Tuttavia, impostare vm.dirty_background_ratio a 5 e vm.dirty_background_bytes al 25% della velocità del disco migliora le prestazioni fino a circa il 25% nella maggior parte dei casi.
vm.dirty_ratio / dirty_bytes
È lo stesso che vm.dirty_background_ratio / dirty_background_bytes, tranne per il fatto che il salvataggio avviene durante la sessione di lavoro, bloccando l'applicazione. Pertanto, vm.dirty_ratio deve essere superiore a vm.dirty_background_ratio. Questo garantisce che i processi in background vengano eseguiti prima per evitare il massimo possibile blocco dell'applicazione. Puoi configurare la differenza tra questi due rapporti in base al carico di input/output del disco.
Risultato
Puoi configurare altre impostazioni per aumentare le prestazioni, ma i miglioramenti saranno minimi e non otterrai benefici significativi. Dobbiamo ricordare che non tutte le impostazioni si applicano a tutti i tipi di applicazioni. Alcune applicazioni funzionano meglio quando configuriamo determinate impostazioni, mentre altre no. Devi trovare il giusto equilibrio tra le configurazioni di queste impostazioni per il carico di lavoro previsto e il tipo di applicazione, e inoltre, quando configuri, è necessario tenere presente il comportamento del sistema operativo. Configurare le impostazioni del kernel non è così semplice come configurare quelle del database: qui è più complicato dare raccomandazioni.
Fonte: habr.com
