Ottimizzazione delle opzioni del kernel Linux per ottimizzare PostgreSQL

Ottimizzazione delle opzioni del kernel Linux per ottimizzare PostgreSQL Le prestazioni ottimali di PostgreSQL dipendono dalle impostazioni del sistema operativo correttamente definite. I parametri del kernel del sistema operativo configurati in modo errato possono rallentare le prestazioni del server del database. Pertanto, è imperativo che queste impostazioni siano configurate in base al server del database e al relativo carico di lavoro. In questo post, discuteremo alcuni degli importanti parametri del kernel Linux che possono influenzare le prestazioni del server di database e come ottimizzarli.

SHMMAX / PICCOLO

SHMMAX è un parametro del kernel utilizzato per determinare la dimensione massima di un singolo segmento di memoria condivisa che un processo Linux può allocare. Prima della versione 9.2, PostgreSQL utilizzava System V (SysV), che richiede l'impostazione SHMMAX. Dopo 9.2 PostgreSQL è passato alla memoria condivisa POSIX. Quindi ora sono richiesti meno byte di memoria condivisa di System V.

Prima della versione 9.3, SHMMAX era il parametro del kernel più importante. Il valore SHMMAX è espresso in byte.

Allo stesso modo, PICCOLO è un altro parametro del kernel usato per determinare
dimensione totale del sistema delle pagine di memoria condivise. Per visualizzare i valori SHMMAX, SHMALL o SHMMIN correnti, utilizzare il comando ipc.

SHM* Dettagli - Linux

$ ipcs -lm

------ Shared Memory Limits --------
max number of segments = 4096
max seg size (kbytes) = 1073741824
max total shared memory (kbytes) = 17179869184
min seg size (bytes) = 1

SHM* Dettagli - MacOS X

$ ipcs -M
IPC status from  as of Thu Aug 16 22:20:35 PKT 2018
shminfo:
	shmmax: 16777216	(max shared memory segment size)
	shmmin:       1	(min shared memory segment size)
	shmmni:      32	(max number of shared memory identifiers)
	shmseg:       8	(max shared memory segments per process)
	shmall:    1024	(max amount of shared memory in pages)

PostgreSQL utilizza IPC di sistema V per allocare memoria condivisa. Questa impostazione è una delle opzioni del kernel più importanti. Ogni volta che ricevi i seguenti messaggi di errore, significa che hai una versione precedente di PostgreSQL e hai un valore SHMMAX molto basso. Gli utenti sono tenuti a regolare e aumentare il valore in base alla memoria condivisa che intendono utilizzare.

Possibili errori di configurazione errata

Se SHMMAX è configurato in modo errato, potresti ricevere un errore quando provi a inizializzare un cluster PostgreSQL con il comando initdb.

Errore initdb
DETAIL: Failed system call was shmget(key=1, size=2072576, 03600).

HINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter. 
You can either reduce the request size or reconfigure the kernel with larger SHMMAX. To reduce the request size (currently 2072576 bytes),
reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.

If the request size is already small, it's possible that it is less than your kernel's SHMMIN parameter,
in which case raising the request size or reconfiguring SHMMIN is called for.

The PostgreSQL documentation contains more information about shared memory configuration. child process exited with exit code 1

Allo stesso modo, potresti ricevere un errore quando avvii il server PostgreSQL usando il comando pg_ctl.

pg_ctl Errore
DETAIL: Failed system call was shmget(key=5432001, size=14385152, 03600).

HINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter.

You can either reduce the request size or reconfigure the kernel with larger SHMMAX.; To reduce the request size (currently 14385152 bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.

If the request size is already small, it's possible that it is less than your kernel's SHMMIN parameter,
in which case raising the request size or reconfiguring SHMMIN is called for.

The PostgreSQL documentation contains more information about shared memory configuration.

Comprensione delle differenze nelle definizioni

La definizione delle opzioni SHMMAX/SHMALL è leggermente diversa su Linux e MacOS X:

  • Linux: kernel.shmmax, kernel.shmall
  • MacOS X: kern.sysv.shmmax, kern.sysv.shmall

Squadra sysctl può essere utilizzato per modificare temporaneamente il valore. Per impostare valori costanti, aggiungi una voce a /etc/sysctl.conf. I dettagli sono di seguito.

Modifica delle opzioni 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 -> 16777216

Modifica delle opzioni 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 -> 16777216

Non dimenticare: per rendere permanenti le modifiche aggiungere questi valori a /etc/sysctl.conf

Pagine enormi

L'impostazione predefinita di Linux è pagine da 4 KB, l'impostazione predefinita di BSD è Super paginee su Windows Grandi pagine. Una pagina è una porzione di RAM allocata a un processo. Un processo può avere più pagine a seconda dei requisiti di memoria. Maggiore è la quantità di memoria richiesta da un processo, maggiore è il numero di pagine che gli vengono assegnate. Il sistema operativo mantiene una tabella di allocazione delle pagine per i processi. Più piccola è la dimensione della pagina, più grande è la tabella, più tempo ci vuole per cercare una pagina in quella tabella di pagine. Pertanto, le pagine di grandi dimensioni consentono di utilizzare una grande quantità di memoria con un sovraccarico ridotto; meno visualizzazioni di pagina, meno errori di pagina, operazioni di lettura/scrittura più veloci grazie a buffer più grandi. Il risultato è un miglioramento delle prestazioni.

PostgreSQL supporta solo pagine di grandi dimensioni su Linux. Per impostazione predefinita, Linux utilizza 4 KB di pagine di memoria, quindi nei casi in cui ci sono troppe operazioni di memoria, è necessario installare pagine più grandi. C'è un aumento delle prestazioni quando si utilizzano pagine di grandi dimensioni da 2 MB e fino a 1 GB. La dimensione della pagina grande può essere impostata al momento del caricamento. Puoi facilmente controllare le opzioni della pagina di grandi dimensioni e il loro utilizzo sulla tua macchina Linux usando il comando cat /proc/meminfo | grep -i enorme.

Ottenere informazioni su pagine di grandi dimensioni (solo Linux)

Note: This is only for Linux, for other OS this operation is ignored$ 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 kB

In questo esempio, sebbene la dimensione della pagina grande sia impostata su 2048 (2 MB), il numero totale di pagine grandi è 0. Ciò significa che le pagine grandi sono disabilitate.

Script per determinare il numero di pagine grandi

Questo semplice script restituisce il numero richiesto di pagine di grandi dimensioni. Esegui lo script sul tuo server Linux mentre PostgreSQL è in esecuzione. Assicurati che la variabile di ambiente sia impostata su $PGDATA viene specificata la directory dei dati 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:     $hp

L'output dello script è simile al seguente:

Uscita dello script

Pid:            12737
VmPeak:         180932 kB
Hugepagesize:   2048 kB
Set Huge Pages: 88

Il valore consigliato per le pagine di grandi dimensioni è 88, quindi dovresti impostarlo su 88.

Installazione di pagine di grandi dimensioni

sysctl -w vm.nr_hugepages=88

Controlla ora le pagine grandi, vedrai che non vengono utilizzate pagine grandi (HugePages_Free = HugePages_Total).

Di nuovo informazioni sulla pagina di grandi dimensioni (solo 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 kB

Ora imposta l'opzione huge_pages su "on" in $PGDATA/postgresql.conf e riavvia il server.

Di nuovo informazioni su 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 kB

Ora puoi vedere che vengono utilizzate pochissime pagine di grandi dimensioni. Proviamo ora ad aggiungere alcuni dati al database.

Alcune operazioni di database per riciclare pagine di grandi dimensioni

postgres=# CREATE TABLE foo(a INTEGER);
CREATE TABLE
postgres=# INSERT INTO foo VALUES(generate_Series(1,10000000));
INSERT 0 10000000

Vediamo se ora stiamo usando pagine più grandi rispetto a prima.

Maggiori informazioni sulle pagine grandi (solo 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 kB

Ora puoi vedere che la maggior parte delle grandi pagine sono in uso.

Nota: il valore di esempio per HugePages utilizzato qui è molto basso, il che non è normale per una macchina di produzione. Si prega di stimare il numero di pagine richiesto per il proprio sistema e di impostarle di conseguenza in base al carico e alle risorse.

vm.swappiness

vm.swappiness è un'altra impostazione del kernel che può influire sulle prestazioni del database. Questa impostazione viene utilizzata per controllare il comportamento di swappiness (paginazione delle pagine all'interno e all'esterno della memoria) su Linux. Il valore va da 0 a 100. Determina la quantità di memoria che verrà impaginata o scaricata. Zero significa nessuna condivisione e 100 significa condivisione aggressiva.

È possibile ottenere buone prestazioni impostando valori inferiori.

L'impostazione su 0 sui kernel più recenti può causare l'interruzione del processo da parte di OOM Killer (il processo di pulizia della memoria di Linux). Quindi è sicuro impostare il valore su 1 se si desidera ridurre al minimo il paging. Il valore predefinito su Linux è 60. Un valore più alto fa sì che la MMU (Memory Management Unit) utilizzi più spazio di scambio rispetto alla RAM, mentre un valore più basso mantiene più dati/codice in memoria.

Un valore inferiore è una buona scommessa per il miglioramento delle prestazioni in PostgreSQL.

vm.overcommit_memory / vm.overcommit_ratio

Le applicazioni acquisiscono memoria e la rilasciano quando non è più necessaria. Ma in alcuni casi, l'applicazione ottiene troppa memoria e non la rilascia. Questo potrebbe innescare un killer OOM. Ecco i possibili valori dei parametri vm.overcommit_memory con una descrizione per ciascuno:

  1. Overcommit euristico (predefinito); euristica basata sul kernel
  2. Consenti comunque l'overcommit
  3. Non esagerare, non superare il rapporto di overcommit.

Riferimento: https://www.kernel.org/doc/Documentation/vm/overcommit-accounting

vm.overcommit_ratio - percentuale di RAM disponibile per l'overload. Un valore del 50% su un sistema con 2 GB di RAM può allocare fino a 3 GB di RAM.

L'impostazione di vm.overcommit_memory su 2 fornisce le migliori prestazioni per PostgreSQL. Questo valore massimizza l'utilizzo della RAM del processo del server senza alcun rischio significativo di essere interrotto dal processo killer OOM. L'applicazione sarà in grado di riavviarsi, ma solo entro il limite di overrun, il che riduce il rischio che il killer OOM interrompa il processo. Pertanto, un valore pari a 2 fornisce prestazioni migliori rispetto al valore predefinito pari a 0. Tuttavia, l'affidabilità può essere migliorata assicurando che la memoria al di fuori dell'intervallo consentito non venga sovraccaricata. Ciò elimina il rischio che il processo venga interrotto dall'OOM-killer.

Sui sistemi non di paging, potrebbe esserci un problema con vm.overcommit_memory impostato su 2.

https://www.postgresql.org/docs/current/static/kernel-resources.html#LINUX-MEMORY-OVERCOMMIT

vm.dirty_ background_ratio / vm.dirty_ background_bytes

vm.dirty_ background_ratio è la percentuale di memoria piena di pagine sporche che devono essere scritte su disco. Lo scaricamento su disco viene eseguito in background. Il valore di questo parametro va da 0 a 100; tuttavia, un valore inferiore a 5 potrebbe non essere efficace e alcuni kernel non lo supportano. 10 è il valore predefinito sulla maggior parte dei sistemi Linux. È possibile migliorare le prestazioni per le operazioni ad alta intensità di scrittura di un fattore minore, il che significa che Linux scaricherà le pagine sporche in background.

Devi impostare il valore vm.dirty_ background_bytes a seconda della velocità del tuo disco.

Non ci sono valori "buoni" per questi due parametri, in quanto entrambi dipendono dall'hardware. Tuttavia, l'impostazione di vm.dirty_background_ratio su 5 e vm.dirty_background_bytes su 25% della velocità del disco migliora le prestazioni fino a circa il 25% nella maggior parte dei casi.

vm.dirty_ratio/dirty_bytes

Questo è lo stesso di vm.dirty_ background_ratio/dirty_ background_bytes, tranne per il fatto che il ripristino viene eseguito in una sessione di lavoro, bloccando l'applicazione. Pertanto vm.dirty_ratio dovrebbe essere superiore a vm.dirty_ background_ratio. Ciò garantisce che i processi in background vengano avviati prima per evitare il blocco dell'applicazione il più possibile. È possibile regolare la differenza tra questi due rapporti in base al carico di I/O del disco.

risultato

Puoi modificare altre impostazioni per migliorare le prestazioni, ma i miglioramenti saranno minimi e non otterrai molti vantaggi. Dobbiamo ricordare che non tutte le opzioni si applicano a tutti i tipi di applicazioni. Alcune app funzionano meglio quando modifichiamo alcune impostazioni e altre no. È necessario trovare il giusto equilibrio tra le configurazioni di queste impostazioni per il carico di lavoro previsto e il tipo di applicazione e il comportamento del sistema operativo deve essere preso in considerazione durante la configurazione. L'ottimizzazione dei parametri del kernel non è facile come configurare i parametri del database: è più difficile dare consigli qui.

Fonte: habr.com

Aggiungi un commento