Performanța optimă a PostgreSQL depinde de parametrii sistemului de operare corect definiți. Parametrii nucleului OS prost configurați pot duce la scăderea performanței serverului de baze de date. Este esențial ca acești parametri să fie configurați în conformitate cu serverul de baze de date și cu sarcina sa de lucru. În această postare, vom discuta câțiva parametri importanți ai nucleului Linux care pot influența performanța serverului de baze de date și metodele de configurare ale acestora.
SHMMAX / SHMALL
SHMMAX — este un parametru de nucleu utilizat pentru a defini dimensiunea maximă a unui segment de memorie partajată (shared memory) pe care un proces Linux îl poate aloca. Până la versiunea 9.2, PostgreSQL utiliza System V (SysV), pentru care este necesară configurarea SHMMAX. După versiunea 9.2, PostgreSQL a trecut la memorie partajată POSIX. Așadar, acum este necesară o cantitate mai mică de memorie partajată System V.
Până la versiunea 9.3, SHMMAX era cel mai important parametru de nucleu. Valoarea SHMMAX este specificată în octeți.
Similar, SHMALL — este un alt parametru de nucleu folosit pentru a determina
volumul total de pagini de memorie partajată (shared memory). Pentru a vizualiza valorile curente SHMMAX, SHMALL sau SHMMIN, utilizați comanda ipcs.
Detalii SHM* — Linux
$ ipcs -lm
------ Limite Memorie Partajată --------
numărul maxim de segmente = 4096
Dimensiunea maximă a segmentului (kbytes) = 1073741824
Total maxim memorie partajată (kbytes) = 17179869184
Dimensiunea minimă a segmentului (octeți) = 1Detalii SHM* — MacOS X
$ ipcs -M
Status IPC de la pe Joi Aug 16 22:20:35 PKT 2018
shminfo:
shmmax: 16777216 (dimensiunea maximă a segmentului de memorie partajată)
shmmin: 1 (dimensiunea minimă a segmentului de memorie partajată)
shmmni: 32 (numărul maxim de identificatori de memorie partajată)
shmseg: 8 (numărul maxim de segmente de memorie partajată pe proces)
shmall: 1024 (cantitatea maximă de memorie partajată în pagini)
PostgreSQL folosește System V IPC pentru a aloca memorie partajată. Acest parametru este unul dintre cei mai importanți parametri ai nucleului. De fiecare dată când primiți următoarele mesaje de eroare, aceasta înseamnă că aveți o versiune mai veche de PostgreSQL și aveți o valoare SHMMAX foarte scăzută. Se așteaptă ca utilizatorii să ajusteze și să crească valoarea în conformitate cu memoria partajată pe care intenționează să o folosească.
Posibile erori de configurare greșită
Dacă SHMMAX este configurat incorect, puteți primi o eroare atunci când încercați să inițializați un cluster PostgreSQL folosind comanda initdb.
Eșec initdb
DETALII: Apelează sistemul a eșuat la shmget(key=1, size=2072576, 03600).
SUGESTIE: Această eroare înseamnă de obicei că cererea PostgreSQL pentru un segment de memorie partajată a depășit parametrul SHMMAX al kernel-ului dumneavoastră.
Puteți fie să reduceți dimensiunea cererii, fie să reconfigurați kernel-ul cu un SHMMAX mai mare. Pentru a reduce dimensiunea cererii (în prezent 2072576 bytes),
reducerea utilizării memoriei partajate PostgreSQL, poate prin reducerea shared_buffers sau max_connections.
Dacă dimensiunea cererii este deja mică, este posibil ca aceasta să fie mai mică decât parametrul SHMMIN al kernel-ului dumneavoastră,
caz în care este necesară creșterea dimensiunii cererii sau reconfigurarea SHMMIN.
Documentația PostgreSQL conține mai multe informații despre configurarea memoriei partajate. Procesul copil a ieșit cu codul de ieșire 1
În mod similar, puteți primi o eroare la pornirea serverului PostgreSQL folosind comanda pg_ctl.
Eșec pg_ctl
DETALII: Apelul de sistem eșuat a fost shmget(key=5432001, size=14385152, 03600).
SUGESTIE: Această eroare înseamnă de obicei că cererea PostgreSQL pentru un segment de memorie partajată a depășit parametrul SHMMAX al kernel-ului dumneavoastră.
Puteți fie să reduceți dimensiunea cererii, fie să reconfigurați kernel-ul cu un SHMMAX mai mare. Pentru a reduce dimensiunea cererii (în prezent 14385152 bytes), reduceți utilizarea memoriei partajate PostgreSQL, poate prin reducerea shared_buffers sau max_connections.
Dacă dimensiunea cererii este deja mică, este posibil ca aceasta să fie mai mică decât parametrul SHMMIN al kernel-ului dumneavoastră,
caz în care este necesară creșterea dimensiunii cererii sau reconfigurarea SHMMIN.
Documentația PostgreSQL conține mai multe informații despre configurarea memoriei partajate.
Înțelegerea diferențelor în definiții
Definiția parametrilor SHMMAX/SHMALL variază puțin în Linux și MacOS X:
- Linux: kernel.shmmax, kernel.shmall
- MacOS X: kern.sysv.shmmax, kern.sysv.shmall
Comanda sysctl poate fi folosit pentru a schimba temporar valoarea. Pentru a stabili valori permanente, adăugați o înregistrare în /etc/sysctl.conf. Detalii sunt prezentate mai jos.
Modificarea parametrilor kernel-ului pe 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 -> 16777216Modificarea parametrilor kernel-ului pe 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 -> 16777216Nu uitați: pentru a face modificările permanente, adăugați aceste valori în /etc/sysctl.conf
Pagini mari (Huge Pages)
În Linux, capacitatea de memorie de 4 KB este utilizată implicit, iar în BSD — Super Pages, iar în Windows — Large Pages. O pagină este o parte a memoriei RAM alocată unui proces. Un proces poate avea mai multe pagini în funcție de cerințele de memorie. Cu cât un proces necesită mai multă memorie, cu atât mai multe pagini îi sunt alocate. SO-ul menține o tabelă de alocare a paginilor pentru procese. Cu cât dimensiunea paginii este mai mică, cu atât tabela este mai mare, ceea ce necesită mai mult timp pentru a căuta o pagină în această tabelă de pagini. Prin urmare, paginile mari permit utilizarea unei cantități mari de memorie cu cheltuieli reduse; mai puține vizualizări de pagini, mai puține erori de pagini, operațiuni de citire/scriere mai rapide prin intermediul bufferelor mari. Ca rezultat — îmbunătățirea performanței.
PostgreSQL suportă pagini mari doar pe Linux. În mod implicit, Linux folosește pagini de memorie de 4 KB, așa că în cazurile în care sunt prea multe operațiuni cu memoria, este necesar să se seteze pagini de dimensiuni mai mari. Se observă o creștere a performanței atunci când se utilizează pagini mari de 2 MB și până la 1 GB. Dimensiunea paginii mari poate fi setată în timpul încărcării. Puteți verifica cu ușurință parametrii paginilor mari și utilizarea acestora pe computerul dumneavoastră Linux, folosind comanda cat /proc/meminfo | grep -i huge.
Obținerea informațiilor despre paginile mari (doar pe Linux)
Notă: Aceasta este doar pentru Linux, pentru alte sisteme de operare această operațiune este ignorată
$ 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În acest exemplu, deși dimensiunea paginii mari este setată la 2048 (2 MB), numărul total de pagini mari are valoarea 0. Aceasta înseamnă că paginile mari sunt dezactivate.
Script pentru determinarea numărului de pagini mari
Acesta este un script simplu care returnează numărul necesar de pagini mari. Rulați scriptul pe serverul dumneavoastră Linux, în timp ce PostgreSQL este activ. Asigurați-vă că variabila de mediu $PGDATA este setată pentru directorul de date PostgreSQL.
Obținerea cifrei necesare de pagini mari
#!/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: $hpIeșirea scriptului arată astfel:
Ieșirea scriptului
Pid: 12737
VmPeak: 180932 kB
Hugepagesize: 2048 kB
Set Huge Pages: 88Valoarea recomandată pentru paginile mari este 88, așa că trebuie să setați valoarea la 88.
Setarea paginilor mari
sysctl -w vm.nr_hugepages=88Verificați paginile mari acum, veți vedea că paginile mari nu sunt utilizate (HugePages_Free = HugePages_Total).
Din nou informații despre paginile mari (doar pe 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 kBAcum setați parametrul huge_pages „on” în $PGDATA/postgresql.conf și reporniți serverul.
Și din nou informații despre paginile mari (doar pe 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 kBAcum puteți vedea că sunt utilizate foarte puține pagini mari. Să încercăm acum să adăugăm unele date în baza de date.
Unele operațiuni cu baza de date pentru gestionarea paginilor mari
postgres=# CREATE TABLE foo(a INTEGER);
CREATE TABLE
postgres=# INSERT INTO foo VALUES(generate_Series(1,10000000));
INSERT 0 10000000Să vedem dacă folosim acum mai multe pagini mari decât înainte.
Încă o dată, informații despre paginile mari (numai pe 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 kBAcum poți vedea că majoritatea paginilor mari sunt utilizate.
Notă: valoarea aproximativă pentru HugePages utilizată aici este foarte mică, ceea ce nu este un lucru normal pentru un sistem în mediu de producție. Te rugăm să evaluezi numărul necesar de pagini pentru sistemul tău și să le configurezi corespunzător în funcție de încărcare și resurse.
vm.swappiness
vm.swappiness — este un alt parametru al kernelului care poate influența performanța bazei de date. Acest parametru este utilizat pentru a gestiona comportamentul swap-ului (swapiness) (schimbarea paginilor în memorie și din memorie) în Linux. Valoarea variază de la 0 la 100. Aceasta determină câtă memorie va fi descărcată sau golită. Zero înseamnă dezactivarea swap-ului, iar 100 înseamnă un swap agresiv.
Poți obține o performanță bună setând valori mai mici.
Setarea valorii 0 în kernel-uri mai noi poate duce la faptul că OOM Killer (procesul de curățare a memoriei în Linux) va închide procesul. Prin urmare, poți seta în siguranță valoarea 1, dacă dorești să minimizezi swap-ul. Valoarea implicită în Linux este 60. O valoare mai mare face ca MMU (unitatea de gestionare a memoriei) să folosească mai mult spațiu de swap decât RAM-ul, în timp ce o valoare mai mică păstrează mai multe date/cod în memorie.
O valoare mai mică este o alegere bună pentru îmbunătățirea performanței în PostgreSQL.
vm.overcommit_memory / vm.overcommit_ratio
Aplicațiile primesc memorie și o eliberează atunci când nu mai este necesară. Dar, în unele cazuri, aplicația primește prea multă memorie și nu o eliberează. Acest lucru poate provoca OOM killer. Iată posibilele valori ale parametrului vm.overcommit_memory cu descriere pentru fiecare:
- Overcommit heuristic (implicit); bazat pe o heuristică a nucleului
- Permite overcommit în orice caz
- Nu exagera, nu depăși coeficientul de overcommit.
Link:
vm.overcommit_ratio — procentul de memorie RAM disponibil pentru suprasarcină. O valoare de 50% într-un sistem cu 2 GB RAM poate aloca până la 3 GB RAM.
O valoare de 2 pentru vm.overcommit_memory asigură o performanță mai bună pentru PostgreSQL. Această valoare maximizează utilizarea memoriei RAM de către procesul serverului fără un risc semnificativ de a fi oprit de procesul OOM killer. Aplicația va putea reporni, dar doar în limitele suprasarcinii, ceea ce reduce riscul ca OOM killer să oprească procesul. Prin urmare, o valoare de 2 oferă o performanță mai bună decât valoarea implicită de 0. Cu toate acestea, fiabilitatea poate fi îmbunătățită prin faptul că memoria dincolo de intervalul permis nu va fi suprasarcină. Acest lucru elimină riscul ca procesul să fie oprit de OOM-killer.
În sistemele fără swap, poate apărea o problemă cu vm.overcommit_memory setat la 2.
vm.dirty_background_ratio / vm.dirty_background_bytes
vm.dirty_background_ratio — este procentul de memorie umplută cu pagini murdare care trebuie scrise pe disc. Scrierea pe disc se face în fundal. Valoarea acestui parametru variază între 0 și 100; totuși, o valoare sub 5 poate fi ineficientă, iar unele kerneluri nu o suportă. 10 este valoarea implicită în majoritatea sistemelor Linux. Puteți îmbunătăți performanța pentru operațiunile cu scriere intensă cu un coeficient mai mic, ceea ce va însemna că Linux va scrie paginile murdare în fundal.
Trebuie să setați valoarea vm.dirty_background_bytes în funcție de viteza discului dumneavoastră.
Pentru acești doi parametri nu există valori „bune”, deoarece ambele depind de hardware. Cu toate acestea, setarea vm.dirty_background_ratio la 5 și vm.dirty_background_bytes la 25% din viteza discului îmbunătățește performanța cu ~ 25% în cele mai multe cazuri.
vm.dirty_ratio / dirty_bytes
Este același lucru cu vm.dirty_background_ratio / dirty_background_bytes, cu excepția faptului că scrierea se efectuează în sesiunea activă, blocând aplicația. Prin urmare, vm.dirty_ratio ar trebui să fie mai mare decât vm.dirty_background_ratio. Acest lucru garantează că procesele din fundal vor fi lansate mai devreme, pentru a evita blocarea maximă a aplicației. Puteți ajusta diferența dintre aceste două rapoarte în funcție de sarcina de intrare-ieșire a discului.
Rezultatul
Puteți configura alte setări pentru a crește performanța, dar îmbunătățirile vor fi minime și nu veți obține beneficii semnificative. Trebuie să ne amintim că nu toate setările se aplică tuturor tipurilor de aplicații. Unele aplicații funcționează mai bine atunci când ajustăm anumite setări, iar altele nu. Trebuie să găsiți echilibrul corect între configurațiile acestor setări pentru sarcina de lucru așteptată și tipul de aplicație, iar la configurare trebuie să luați în considerare comportamentul sistemului de operare. Configurarea parametrilor nucleului nu este la fel de simplă ca ajustarea setărilor bazei de date: aici este mai complicat să ofereți recomandări.
Sursa: habr.com
