2015. gada Alekseja Lesovska ziÅojuma "Deep dive into PostgreSQL internal statistics" atÅ”ifrÄjums.
ZiÅojuma autora atruna: NorÄdu, ka Å”is ziÅojums datÄts ar 2015. gada novembri ā pagÄjuÅ”i vairÄk nekÄ 4 gadi un ir pagÄjis daudz laika. ZiÅojumÄ aplÅ«kotÄ versija 9.4 vairs netiek atbalstÄ«ta. PÄdÄjo 4 gadu laikÄ ir izlaisti 5 jauni laidieni, kuros parÄdÄ«jÄs daudz jauninÄjumu, uzlabojumu un izmaiÅu attiecÄ«bÄ uz statistiku, un daļa materiÄla ir novecojusi un nav aktuÄla. PÄrskatīŔanas procesÄ es centos iezÄ«mÄt Ŕīs vietas, lai neievilinÄtu tevi, lasÄ«tÄj, maldu lamatÄs. TomÄr es neizvÄlÄjos pÄrrakstÄ«t Ŕīs vietas, to ir ļoti daudz, un beigÄs sanÄks pilnÄ«gi cits ziÅojums.
DatubÄze PostgreSQL ir liels mehÄnisms, kas sastÄv no daudziem apakÅ”sistÄmÄm, kuru koordinÄta darbÄ«ba tieÅ”i ietekmÄ datubÄzes veiktspÄju. EkspluatÄcijas procesÄ tiek nodroÅ”inÄta statistikas un informÄcijas par komponentu darbÄ«bu apkopoÅ”ana, kas ļauj novÄrtÄt PostgreSQL efektivitÄti un veikt pasÄkumus veiktspÄjas uzlaboÅ”anai. TomÄr Ŕīs informÄcijas ir ļoti daudz un tÄ tiek piedÄvÄta diezgan vienkÄrÅ”otÄ veidÄ. Å Ä«s informÄcijas apstrÄde un interpretÄcija reizÄm ir visai netriviÄla uzdevums, un "zoodÄrzs" rÄ«ku un utilÄ«tu var viegli apjukt pat pieredzÄjuÅ”u DBA.


Labdien! Mans vÄrds ir Aleksejs. KÄ Iļja teica, es stÄstīŔu par PostgreSQL statistiku.

PostgreSQL aktivitÄtes statistika. PostgreSQL ir divas statistikas. AktivitÄtes statistika, par kuru bÅ«s runa. Un plÄnotÄja statistika par datu sadalÄ«jumu. Es stÄstīŔu tieÅ”i par PostgreSQL aktivitÄtes statistiku, kas ļauj mums spriest par veiktspÄju un kaut kÄ to uzlabot.
PastÄstīŔu, kÄ efektÄ«vi izmantot statistiku dažÄdu problÄmu risinÄÅ”anai, kas jums raduÅ”Äs vai varÄtu rasties.

Ko ziÅojumÄ nebÅ«s? ZiÅojumÄ es netikÅ”u pie plÄnotÄja statistikas, jo tÄ ir atseviŔķa tÄma atseviŔķam ziÅojumam par to, kÄ dati tiek glabÄti datubÄzÄ un par to, kÄ plÄnotÄjs iegÅ«st priekÅ”statu par Å”o datu kvalitatÄ«vÄm un kvantitatÄ«vÄm Ä«paŔībÄm.
Un nebÅ«s arÄ« rÄ«ku apskatu, es nesalÄ«dzinÄÅ”u vienu produktu ar citu. NekÄdas reklÄmas nebÅ«s. AtmetÄ«sim to.

Es vÄlos jums parÄdÄ«t, ka statistikas izmantoÅ”ana ir noderÄ«ga. Tas ir nepiecieÅ”ams. To izmantot nav grÅ«ti. Mums bÅ«s nepiecieÅ”ams tikai parasts SQL un pamatzinÄÅ”anas par SQL.
Un runÄsim par to, kÄdu statistiku izvÄlÄties problÄmu risinÄÅ”anai.

Ja mÄs paskatÄmies uz PostgreSQL un operÄtÄjsistÄmÄ izpildÄ«sim komandu, lai apskatÄ«tu procesus, mÄs redzÄsim "melno kÄrbu". MÄs redzÄsim dažus procesus, kas kaut ko dara, un pÄc nosaukuma varam aptuveni iedomÄties, ko tie dara. Bet, bÅ«tÄ«bÄ, tas ir melns kÄrba, iekÅ”Ä mÄs ieskatÄ«ties nevaram.
MÄs varam aplÅ«kot procesora slodzi top, varam pÄrbaudÄ«t atmiÅas izmantoÅ”anu ar kÄdÄm sistÄmas utilÄ«tÄm, bet ieskatÄ«ties PostgreSQL iekÅ”pusÄ mÄs nevarÄsim. Tam mums ir nepiecieÅ”ami citi rÄ«ki.

Un turpinot, es pastÄstīŔu, uz kurieni tiek tÄrÄts laiks. Ja mÄs iedomÄjamies PostgreSQL kÄ Å”Ädu shÄmu, tad mÄs varam atbildÄt, uz kurieni tiek tÄrÄts laiks. Tas ir divas lietas: klientu pieprasÄ«jumu apstrÄde no lietotnÄm un foniskie uzdevumi, ko PostgreSQL veic, lai nodroÅ”inÄtu savu darbspÄju.
Ja mÄs sÄkam apskatÄ«t no kreisÄ augÅ”ÄjÄ stÅ«ra, mÄs varam izsekot, kÄ tiek apstrÄdÄti klientu pieprasÄ«jumi. PieprasÄ«jums nÄk no lietotnes un nÄkamajai darbÄ«bai tiek atvÄrta klienta sesija. PieprasÄ«jums tiek nodots plÄnotÄjam. PlÄnotÄjs izveido pieprasÄ«juma plÄnu. To nosÅ«ta tÄlÄk izpildei. Notiek kÄda bloku I/O operÄcija, saistÄ«ta ar tabulÄm un indeksiem. NepiecieÅ”amie dati tiek nolasÄ«ti no diskiem atmiÅÄ speciÄlÄ apgabalÄ "shared buffers". PieprasÄ«juma rezultÄti, ja tas ir updates, deletes, tiek fiksÄti darÄ«jumu žurnÄlÄ WAL. Dažas statistikas informÄcija nonÄk žurnÄlÄ vai statistikas kolektorÄ. Un pieprasÄ«juma rezultÄts tiek nodots atpakaļ klientam. PÄc tam klients var atkÄrtot visu ar jaunu pieprasÄ«jumu.
KÄdas ir mÅ«su fonisko uzdevumu un fonisko procesu Ä«paŔības? Mums ir vairÄki procesi, kas nodroÅ”ina darbÄ«bu un uztur datu bÄzi normÄlÄ darba režīmÄ. Å ie procesi tiks skarti arÄ« ziÅojumÄ: tas ir autovacuum, checkpointer, procesi, kas saistÄ«ti ar replikÄciju, background writer. Par katru no tiem es runÄÅ”u ziÅojuma gaitÄ.

KÄdas problÄmas ir saistÄ«tas ar statistiku?
- InformÄcijas ir daudz. PostgreSQL 9.4 nodroÅ”ina 109 metriku datu statistikas skatīŔanai. TomÄr, ja datubÄzÄ ir daudz tabulu, shÄmu un datubÄžu, tad visas Ŕīs metrikas bÅ«s jÄreizina ar attiecÄ«go tabulu un datubÄzu skaitu. T. i., informÄcijas kļūst vÄl vairÄk. Un tajÄ Ä¼oti viegli iegrimt.
- NÄkamÄ problÄma ir tÄ, ka statitika tiek attÄlota skaitÄ«tÄju formÄ. Ja mÄs aplÅ«kojam Å”o statistiku, mÄs redzÄsim pastÄvÄ«gi pieaugoÅ”us skaitÄ«tÄjus. Ja no statistikas dzÄÅ”anas brīža ir pagÄjis ļoti ilgs laiks, mÄs redzÄsim miljardiem vÄrtÄ«bas. Un tÄs mums neko nepasaka.
- Nav vÄstures. Ja jums ir notikusi kÄda kļūme, kas notika 15-30 minÅ«tes atpakaļ, jÅ«s nevarat izmantot statistiku, lai uzzinÄtu, kas notika 15-30 minÅ«tes iepriekÅ”. TÄ ir problÄma.
- IekļautÄ rÄ«ka trÅ«kums PostgreSQL ir problÄma. Koda izstrÄdÄtÄji nesniedz nekÄdu utilÄ«tu. ViÅiem nav nekÄda lÄ«dzÄ«ga. ViÅi vienkÄrÅ”i sniedz statistiku datubÄzÄ. Izmantojiet to, veiciet ar to pieprasÄ«jumus, dariet, ko vÄlaties.
- TÄ kÄ iekļautÄ rÄ«ka PostgreSQL nav, tas ir iemesls citai problÄmai. Daudzas treÅ”o puÅ”u lietotnes. Katrs uzÅÄmums, kuram ir vairÄk vai mazÄk prasÄ«gas rokas, mÄÄ£ina izstrÄdÄt savu programmu. Un rezultÄtÄ kopienÄ ir ļoti daudz rÄ«ku, kurus var izmantot statistikas apstrÄdei. Un vieniem rÄ«kiem ir noteiktas iespÄjas, citiem rÄ«kiem nav citu iespÄju, vai arÄ« ir kÄdas jaunas iespÄjas. Un rodas situÄcija, kad ir nepiecieÅ”ams izmantot divus, trÄ«s, Äetrus rÄ«kus, kas viens otru pÄrklÄj un kuriem ir dažÄdas funkcijas. Tas ir ļoti nepatÄ«kami.

Ko no tÄ var secinÄt? Ir svarÄ«gi spÄt iegÅ«t statistiku tieÅ”i, lai nepaļautos uz programmÄm, vai arÄ« kÄdÄ veidÄ uzlabot Ŕīs programmas: pievienojot noteiktas funkcijas, lai gÅ«tu savu labumu.
Un ir nepiecieÅ”amas pamatzinÄÅ”anas SQL. Lai iegÅ«tu datus no statistikas, ir jÄformulÄ SQL pieprasÄ«jumi, t. i., jums jÄzina, kÄ sastÄdÄ«t select, join.

Statistika piedÄvÄ mums vairÄkas lietas. TÄs var iedalÄ«t kategorijÄs.
- PirmÄ kategorija ir notikumi, kas notiek datubÄzÄ. Tas ir tad, kad datubÄzÄ notiek kÄds notikums: pieprasÄ«jums, piekļuve tabulai, automÄtiskÄ vakumÄÅ”ana, apstiprinÄjumi ā tas viss ir notikumi. AttiecÄ«gajiem notikumiem skaitÄ«tÄji tiek incrementÄti. MÄs varam izsekot Å”iem notikumiem.
- OtrÄ kategorija ir objektu Ä«paŔības, piemÄram, tabulas, datubÄzes. TÄm ir Ä«paŔības. Tas ir tabulu izmÄrs. MÄs varam izsekot tabulu izaugsmei, indeksu pieaugumam. MÄs varam apskatÄ«t izmaiÅas dinamiskÄ veidÄ.
- Un treÅ”Ä kategorija ir laiks, kas nepiecieÅ”ams notikumam. PieprasÄ«jums ir notikums. Tam ir sava konkrÄta ilguma mÄra. Å eit tas sÄkÄs, Å”eit tas beidzÄs. MÄs varam to izsekot. Vai arÄ« laiks, kas nepiecieÅ”ams bloka lasīŔanai no diska vai ierakstīŔanai. TÄdas lietas arÄ« tiek izsekotas.

Statistikas avoti ir Å”Ädi:
- KopÄ«gajÄ atmiÅÄ (shared buffers) ir segments, lai tur ievietotu statiskos datus; tur ir arÄ« tie paÅ”i skaitÄ«tÄji, kas pastÄvÄ«gi tiek incrementÄti, kad notiek kÄdi notikumi vai rodas kÄdi momenti datubÄzes darbÄ«bÄ.
- Visi Å”ie skaitÄ«tÄji nav pieejami lietotÄjam un pat nav pieejami administratoram. Tie ir zema lÄ«meÅa dati. Lai pie tiem piekļūtu, PostgreSQL piedÄvÄ interfeisu SQL funkciju veidÄ. MÄs varam veikt select vaicÄjumus, izmantojot Ŕīs funkcijas, un iegÅ«t kÄdu metriku (vai metrikas kopumu).
- TomÄr izmantot Ŕīs funkcijas vienmÄr nav Ärti, tÄpÄc funkcijas kalpo kÄ pamats skatu (VIEWs) izveidoÅ”anai. Tie ir virtuÄli tabulas, kas sniedz statistiku par kÄdu konkrÄtu apakÅ”sistÄmu vai kÄdu grupu notikumu datubÄzÄ.
- Å ie iebÅ«vÄtie skatÄ«jumi (VIEWs) ir galvenais lietotÄja interfeiss statistikas apstrÄdÄ. Tie ir pieejami noklusÄti bez papildu konfigurÄcijas, varat to uzreiz izmantot, apskatÄ«t, Åemt no turienes informÄciju. Ir arÄ« contrib pakotnes. Ir oficiÄlas contrib pakotnes. JÅ«s varat instalÄt postgresql-contrib pakotni (piemÄram, postgresql94-contrib), ielÄdÄt nepiecieÅ”amo moduli konfigurÄcijÄ, norÄdÄ«t tam parametrus, restartÄt PostgreSQL un varat to lietot. (PiezÄ«me. AtkarÄ«bÄ no izplatīŔanas, pÄdÄjÄs versijÄs contrib pakotne ir daļa no galvenÄs pakotnes.).
- Ir pastÄv neoficiÄlie contrib. Tie netiek piegÄdÄti ar standarta PostgreSQL komplektu. Tos nepiecieÅ”ams vai nu kompilÄt, vai instalÄt kÄ bibliotÄku. Varianti var bÅ«t ļoti dažÄdi, atkarÄ«bÄ no tÄ, ko izstrÄdÄtÄjs ir izdomÄjis Å”im neoficiÄlajam contrib.

Å ajÄ slaidÄ ir attÄloti visi tie skati (VIEWs) un daļa no funkcijÄm, kas ir pieejamas PostgreSQL 9.4. KÄ redzam, to ir daudz. Un ir diezgan viegli apjukt, ja ar to saskaras pirmo reizi.

TomÄr, ja mÄs paÅemam iepriekÅ”Äjo attÄlu KÄ tiek iztÄrÄts laiks uz PostgreSQL un salÄ«dzinÄm ar Å”o sarakstu, tad iegÅ«stam Å”Ädu attÄlu. Katru skatu (VIEWs) vai katru funkciju mÄs varam izmantot dažÄdiem mÄrÄ·iem, lai iegÅ«tu atbilstoÅ”o statistiku, kad darbojas PostgreSQL. Un mÄs varam saÅemt kÄdu informÄciju par apakÅ”sistÄmas darbÄ«bu.

Pirmais, ko mÄs aplÅ«kosim, ir pg_stat_database. KÄ redzam, Å”is ir skats. TajÄ ir daudz informÄcijas. Ä»oti dažÄda informÄcija. Un tÄ sniedz ļoti noderÄ«gas zinÄÅ”anas par to, kas notiek mÅ«su datu bÄzÄ.
Ko noderÄ«gu mÄs varam no turienes iegÅ«t? SÄksim ar paÅ”Äm vienkÄrÅ”ÄkajÄm lietÄm.

select
sum(blks_hit)*100/sum(blks_hit+blks_read) as hit_ratio
from pg_stat_database;Pirmais, ko mÄs varam apskatÄ«t, ir procentuÄlais kopsummas rÄdÄ«tÄjs. ProcentuÄlais kopsummas rÄdÄ«tÄjs ir noderÄ«ga metrika. TÄ Ä¼auj novÄrtÄt, cik liels datu apjoms tiek Åemts no shared buffers keÅ”atmiÅas, un cik liels datu apjoms tiek nolasÄ«ts no diska.
Saprotams, ka jo lielÄks mÅ«su keÅ”atmiÅas trÄpÄ«jums, jo labÄk. MÄs Å”o metrikas rÄdÄ«tÄju novÄrtÄjam kÄ procentu. Un, piemÄram, ja mÅ«su keÅ”atmiÅas trÄpÄ«juma procents pÄrsniedz 90 %, tad tas ir labi. Ja tas pazeminÄs zem 90 %, tas nozÄ«mÄ, ka mums nepietiek atmiÅas, lai saglabÄtu karstos "datus" atmiÅÄ. Un, lai izmantotu Å”os datus, PostgreSQL ir spiests piekļūt diskam, un tas ir lÄnÄk nekÄ tad, ja dati tiktu nolasÄ«ti no atmiÅas. JÄdomÄ par atmiÅas palielinÄÅ”anu: vai nu palielinÄt shared buffers, vai pievienot vairÄk fiziskÄs atmiÅas (RAM).

select
datname,
(xact_commit*100)/(xact_commit+xact_rollback) as c_ratio,
deadlocks, conflicts,
temp_file, pg_size_pretty(temp_bytes) as temp_size
from pg_stat_database;Ko vÄl varam Åemt no Ŕī skatÄ«juma? Varam apskatÄ«t anomÄlijas, kas notiek datu bÄzÄ. Ko Å”eit rÄda? Å eit ir commits, rollbacks, pagaidu failu izveide, to apjoms, deadlocks un konflikti.
MÄs varam izmantot Å”o vaicÄjumu. Å is SQL ir diezgan vienkÄrÅ”s. Un mÄs varam apskatÄ«t Å”os datus pie sevis.

Un Å”eit uzreiz ir sliekÅ”Åa vÄrtÄ«bas. MÄs skatÄmies attiecÄ«bu starp commits un rollbacks. Commits ā tas ir veiksmÄ«gs darÄ«juma apstiprinÄjums. Rollbacks ā tas ir atcelÅ”ana, t. i., darÄ«jums veica kÄdu darbu, noslogoja datubÄzi, kaut ko skaitÄ«ja, bet pÄc tam notika kļūda un darÄ«juma rezultÄti tiek noraidÄ«ti. T. i. pÄrÄk liels skaits rollbacks ir slikti. Un bÅ«tu jÄizvairÄs no tiem un jÄpÄrskata kods, lai tÄ nenotiktu.
Konflikti (conflicts) ir saistÄ«ti ar replikÄciju. Un tiem arÄ« vajadzÄtu iztÄ«rÄ«t. Ja jums ir kÄdi vaicÄjumi, kas tiek izpildÄ«ti replikÄ un rodas konflikti, tad jÄizpÄta Å”ie konflikti, jÄskatÄs, kas notiek. DetalizÄti var atrast žurnÄlos. Un jÄnovÄrÅ” konfliktainas situÄcijas, lai aplikÄcijas vaicÄjumi darbotos bez kļūdÄm.
Deadlocks ā tÄ ir arÄ« slikta situÄcija. Kad vaicÄjumi sacenÅ”as par resursiem, viens vaicÄjums piekļūst vienam resursam un iegÅ«st slÄgÅ”anu, otrs vaicÄjums piekļūst otram resursam un arÄ« iegÅ«st slÄgÅ”anu, bet pÄc tam abi vaicÄjumi piekļūst viens otra resursiem un bloÄ·Äjas gaidot, kad kaimiÅÅ” atbrÄ«vos slÄgÅ”anu. Tas ir arÄ« problemÄtisks stÄvoklis. Tos jÄrisina, pÄrstrÄdÄjot aplikÄcijas un sÄrijveidÄ piekļūstot resursiem. Un, ja jÅ«s redzat, ka jÅ«su deadlocks pastÄvÄ«gi palielinÄs, ir jÄskatÄs detaļas žurnÄlos, jÄizpÄta raduÅ”Äs situÄcijas un jÄpÄrbauda, kur ir problÄma.
Pagaidu faili (temp_files) ā tas ir arÄ« slikti. Kad lietotÄja vaicÄjumam trÅ«kst atmiÅas, lai novietotu operatÄ«vos, pagaidu datus, tas izveido diska failu. Un visas operÄcijas, kuras tas varÄja veikt pagaidu buferÄ« atmiÅÄ, sÄk veikt jau uz diska. Tas ir lÄni. Tas palielina vaicÄjuma izpildes laiku. Un klients, kas nosÅ«tÄ«ja vaicÄjumu uz PostgreSQL, saÅems atbildi nedaudz vÄlÄk. Ja visas Ŕīs operÄcijas tiks veiktas atmiÅÄ, Postgres atbildÄs daudz ÄtrÄk un klients gaidÄ«s mazÄk.

Pg_stat_bgwriter ā Å”is skats apraksta divu fona apakÅ”sistÄmu darbu PostgreSQL: tas ir checkpointer un fona rakstÄ«tÄjs.

Vispirms izpÄtÄ«sim kontrolpunktus, t. i. checkpoints. Kas ir kontrolpunkti? Kontrolpunkts ir pozÄ«cija transakciju žurnÄlÄ, kas norÄda, ka visi datu izmaiÅas, kas fiksÄtas žurnÄlÄ, ir veiksmÄ«gi sinhronizÄtas ar datiem diskÄ. Process, atkarÄ«bÄ no slodzes un iestatÄ«jumiem, var bÅ«t gara un lielÄkoties sastÄv no netÄ«ro lapu sinhronizÄcijas koplietojamo buferu ar datu failiem diskÄ. KÄpÄc tas ir nepiecieÅ”ams? Ja PostgreSQL pastÄvÄ«gi piekļūtu diskam un Åemtu datus no turienes un rakstÄ«tu datus katru reizi, kad piekļūtu, tas bÅ«tu lÄni. TÄpÄc PostgreSQL ir atmiÅas segments, kura lielums ir atkarÄ«gs no konfigurÄcijas parametriem. Postgres Å”ajÄ atmiÅÄ ievieto operatÄ«vos datus turpmÄkai apstrÄdei vai izsniegÅ”anai pÄc pieprasÄ«juma. Ja notiek pieprasÄ«jumi uz datu izmaiÅÄm, tad tÄs tiek mainÄ«tas. Un mÄs saÅemam divas datu versijas. Viena ir mÅ«su atmiÅÄ, otra diskÄ. Un periodiski ir jÄsinhronizÄ Å”ie dati. Mums ir jÄsinhronizÄ tas, kas ir mainÄ«ts atmiÅÄ, uz disku. Tam ir nepiecieÅ”ams kontrolpunkts.
Kontrolpunkts iziet cauri koplietojamiem buferiem, atzÄ«mÄ netÄ«ras lapas, ka tÄs ir nepiecieÅ”amas kontrolpunktam. PÄc tam viÅÅ” veic otro gÄjienu pa koplietojamiem buferiem. Un lapas, kas ir atzÄ«mÄtas kontrolpunktam, viÅÅ” jau sinhronizÄ. TÄdÄjÄdi notiek datu sinhronizÄcija ar disku.
Ir divu veidu kontrolpunkti. Viens kontrolpunkts tiek veikts pÄc laika intervÄla. Å is kontrolpunkts ir noderÄ«gs un labs ā checkpoint_timed. Un ir kontrolpunkti pÄc pieprasÄ«juma ā checkpoint required. Å Äds kontrolpunkts notiek, kad mums ir ļoti liela datu rakstīŔana. MÄs esam ierakstÄ«juÅ”i ļoti daudz transakciju žurnÄlu. Un PostgreSQL uzskata, ka tam ir nepiecieÅ”ams visu to sinhronizÄt pÄc iespÄjas ÄtrÄk, veikt kontrolpunktu un turpinÄt dzÄ«vot.
Un, ja jÅ«s esat skatÄ«jies statistiku pg_stat_bgwriter un redzÄjÄt, ka jums checkpoint_req ir daudz lielÄks nekÄ checkpoint_timed, tad tas ir slikti. KÄpÄc slikti? Tas nozÄ«mÄ, ka PostgreSQL atrodas pastÄvÄ«gÄ stresa situÄcijÄ, kad tam ir jÄieraksta dati diskÄ. Kontrolpunkts pÄc laika intervÄla ir mazÄk stresa un tiek veikts saskaÅÄ ar iekÅ”Äjo grafiku un ir kÄ izstiepts laika posms. PostgreSQL ir iespÄja veikt pÄrtraukumus darbÄ un nenoslogot diskusistÄmu. Tas ir labvÄlÄ«gi PostgreSQL. Un pieprasÄ«jumi, kas tiek izpildÄ«ti kontrolpunkta laikÄ, neizjutÄ«s stresu no tÄ, ka diskusistÄma ir aizÅemta.
Un checkpoint regulÄÅ”anai ir trÄ«s parametri:
checkpoint_segments.checkpoint_timeout.checkpoint_completion_target.
Tie ļauj regulÄt kontrolpunktu darbÄ«bu. Bet es par tiem neapstÄÅ”os. To ietekme ir jau atseviŔķa tÄma.
UzmanÄ«bu: PÄrskatÄ aplÅ«kotÄ versija 9.4 jau nav aktuÄla. MÅ«sdienu PostgreSQL versijÄs parametrs checkpoint_segments ir aizstÄts ar parametriem min_wal_size un max_wal_size.

NÄkamÄ apakÅ”sistÄma ir fona rakstÄ«tÄjs ā fona rakstÄ«tÄjs. Ko viÅÅ” dara? ViÅÅ” strÄdÄ pastÄvÄ«gi bezgalÄ«gÄ ciklÄ. ViÅÅ” skenÄ lapas kopshared buffers un tÄ«ras lapas, kuras viÅÅ” atrada, nospiež uz diska. TÄdÄjÄdi viÅÅ” palÄ«dz checkpointer āam paveikt mazÄk darba kontrolpunktu izpildes procesÄ.
KÄpÄc viÅÅ” vÄl ir nepiecieÅ”ams? ViÅÅ” nodroÅ”ina vajadzÄ«bu pÄc tÄ«rÄm lapÄm kopshared buffers, ja tÄs pÄkÅ”Åi nepiecieÅ”amas (lielÄ skaitÄ un uzreiz) datu izvietoÅ”anai. PieÅemsim, ka radusies situÄcija, kad, lai izpildÄ«tu pieprasÄ«jumu, nepiecieÅ”amas tÄ«ras lapas, un tÄs jau ir kopshared buffers. Postgres backend to vienkÄrÅ”i Åem un izmanto, viÅam paÅ”am nevajag neko tÄ«rÄ«t. Bet, ja tÄdu lapu nav, backend aptur darbu un sÄk meklÄt lapas, lai nospiestu tÄs uz diska un izmantotu savÄm vajadzÄ«bÄm ā tas negatÄ«vi ietekmÄ izpildÄmo pieprasÄ«jumu laiku. Ja redzat, ka jÅ«su parametrs maxwritten_clean ir liels, tas nozÄ«mÄ, ka fona rakstÄ«tÄjs netiek galÄ ar savu uzdevumu un ir jÄpalielina parametri bgwriter_lru_maxpages, lai viÅÅ” varÄtu vienÄ ciklÄ paveikt vairÄk darba, vairÄk notÄ«rÄ«t lapas.
Un vÄl viens ļoti noderÄ«gs rÄdÄ«tÄjs ā tas ir buffers_backend_fsync. Backend netiek veikta fsync, jo tas ir lÄni. ViÅi nodod fsync augstÄk IO stakÄ checkpointer āam. Checkpointer āam ir savs gaidīŔanas rindas process, viÅÅ” periodiski apstrÄdÄ fsync un sinhronizÄ lapas atmiÅÄ ar failiem diskÄ. Ja checkpointer āa gaidīŔanas rinda ir liela un piepildÄ«ta, backend ir spiests pats veikt fsync un tas lÄni ietekmÄ backend darbÄ«bu,, t.i., klients saÅems atbildi vÄlÄk, nekÄ varÄtu. Ja redzat, ka Ŕī vÄrtÄ«ba ir lielÄka par nulli, tad tas jau ir problÄma un ir jÄpieverÅ” uzmanÄ«ba fona rakstÄ«tÄja iestatÄ«jumiem un arÄ« jÄnovÄrtÄ diska apakÅ”sistÄmas veiktspÄja.

UzmanÄ«bu: _NÄkamais teksts apraksta statistiskos attÄlojumus, kas saistÄ«ti ar replikÄciju. LielÄkÄ daļa attÄlojumu un funkciju nosaukumu tika pÄrdÄvÄti Postgres 10. PÄrdÄvÄÅ”anas bÅ«tÄ«ba bija nosaukumu nomaiÅa xlog uz wal un location uz lsn funkciju un attÄlojumu nosaukumos un tamlÄ«dzÄ«gi. KonkretÄs piemÄrs, funkcija pg_xlog_location_diff() tika pÄrdÄvÄta kÄ pg_wal_lsn_diff()._
Å eit mums arÄ« ir daudz dažÄdu lietu. Bet mums bÅ«s nepiecieÅ”ami tikai punkti, kas saistÄ«ti ar location.

Ja mÄs redzam, ka visi vÄrtÄ«bas ir vienÄdas, tad tas ir ideÄls variants, un replikÄcija nepaliek aiz meistara.
Å Ä« seÅ”u zÄ«mju pozÄ«cija ir pozÄ«cija darÄ«jumu žurnÄlÄ. TÄ pastÄvÄ«gi palielinÄs, ja datu bÄzÄ ir kÄda aktivitÄte: insert, delete utt.

cik xlog ir uzrakstīts baitos
$ select
pg_xlog_location_diff(pg_current_xlog_location(),'0/00000000');
replikÄcijas aizture baitos
$ select
client_addr,
pg_xlog_location_diff(pg_current_xlog_location(), replay_location)
from pg_stat_replication;
replikÄcijas aizture sekundÄs
$ select
extract(epoch from now() - pg_last_xact_replay_timestamp());Ja Ŕīs lietas atŔķiras, tÄtad ir kÄda aizture. Aizture ā tas ir replikas aizkavÄÅ”anÄs pret meistaru, tas ir, dati atŔķiras starp serveriem.
Ir trÄ«s iemesli aizkavÄÅ”anai:
- Tas ir disku subsistÄmas nepietiekama jauda, lai pareizi pierakstÄ«tu failu sinhronizÄciju.
- Tas var bÅ«t iespÄjamÄs tÄ«kla kļūdas vai tÄ«kla sastrÄgumi, kad dati netiek laikus nogÄdÄti replikÄ, un tas tos nevar reproducÄt.
- Un procesors. Procesors ir ļoti reta situÄcija. Un es tÄdu esmu redzÄjis divas vai trÄ«s reizes, bet tas tÄ var bÅ«t.
Un Å”ie trÄ«s vaicÄjumi, kas ļauj mums izmantot statistiku. MÄs varam novÄrtÄt, cik daudz ir uzrakstÄ«ts mÅ«su darÄ«jumu žurnÄlÄ. Ir Ŕī funkcija pg_xlog_location_diff un varam novÄrtÄt replikÄcijas aizturi baitos un sekundÄs. MÄs arÄ« izmantojam Å”o vÄrtÄ«bu no Ŕī attÄlojuma (VIEWs).
PiezÄ«me: _PÄr pg_xlog_locationdiff() funkcijÄm var izmantot atÅemÅ”anas operatoru un atÅemt vienu pozÄ«ciju no otras. Tas ir Ärti.
RunÄjot par aizturi, kas ir sekundÄs, ir viens moments. Ja meistara pusÄ nenotiek nekÄda aktivitÄte, darÄ«jums tur bija pirms 15 minÅ«tÄm, un nav nekÄdas aktivitÄtes, ja mÄs Å”ajÄ brÄ«dÄ« pÄrbaudÄm Å”o aizturi replikÄ, mÄs redzÄsim 15 minūŔu aizturi. Par to jÄatceras. Tas var apmulst, kad jÅ«s skatÄties Å”o aizturi.

Pg_stat_all_tables ā vÄl viena noderÄ«ga apskate. TÄ rÄda statistiku par tabulÄm. Kad mÅ«su datubÄzÄ ir tabulas, kurÄm ir kÄda aktivitÄte, kÄdas darbÄ«bas, mÄs varam Å”o informÄciju iegÅ«t no Ŕīs apskates.

select
relname,
pg_size_pretty(pg_relation_size(relname::regclass)) as size,
seq_scan, seq_tup_read,
seq_scan / seq_tup_read as seq_tup_avg
from pg_stat_user_tables
where seq_tup_read > 0 order by 3,4 desc limit 5;Pirmais, ko varam apskatÄ«t, ir secÄ«gÄs skenÄÅ”anas pÄc tabulas. Pats skaitlis pÄc Å”iem pÄrejÄm vÄl nav obligÄti slikts un nepierÄda, ka mums jau kaut kas jÄdara.
TomÄr ir otrÄ metrika ā seq_tup_read. Tas ir to rindu skaits, kas atgrieztas secÄ«gÄs skenÄÅ”anas rezultÄtÄ. Ja vidÄjais skaitlis pÄrsniedz 1 000, 10 000, 50 000, 100 000, tad tas jau ir rÄdÄ«tÄjs, ka varbÅ«t jums ir jÄpievieno indekss, lai piekļuves notiktu pÄc indeksa, vai varbÅ«t optimizÄt vaicÄjumus, kas izmanto Å”Ädas secÄ«gas skenÄÅ”anas, lai to nepieļautu.
VienkÄrÅ”s piemÄrs ā pieÅemsim, ka vaicÄjums ar lielu OFFSET un LIMIT ir izpildÄms. PiemÄram, tiek skenÄtas 100 000 rindas tabulÄ, un pÄc tam tiek apkopotas 50 000 vajadzÄ«gÄs rindas, bet iepriekÅ”ÄjÄs skenÄtÄs rindas tiek noraidÄ«tas. Tas arÄ« ir slikts gadÄ«jums. Un Å”Ädus vaicÄjumus ir jÄoptimizÄ. Å eit ir tÄds vienkÄrÅ”s SQL vaicÄjums, ar kuru var apskatÄ«t un novÄrtÄt iegÅ«tÄs ciparnotes.

select
relname,
pg_size_pretty(pg_total_relation_size(relname::regclass)) as
full_size,
pg_size_pretty(pg_relation_size(relname::regclass)) as
table_size,
pg_size_pretty(pg_total_relation_size(relname::regclass) -
pg_relation_size(relname::regclass)) as index_size
from pg_stat_user_tables
order by pg_total_relation_size(relname::regclass) desc limit 10;Tabulu izmÄrus var iegÅ«t arÄ« ar Ŕīs tabulas palÄ«dzÄ«bu un, izmantojot papildu funkcijas. pg_total_relation_size(), pg_relation_size().
ÄŖpaÅ”i ir metakomandas dt un di, kuras var izmantot PSQL un arÄ« apskatÄ«t tabulu un indeksu izmÄrus.
TomÄr funkciju izmantoÅ”ana palÄ«dz mums apskatÄ«t tabulu izmÄrus, Åemot vÄrÄ indeksus vai neÅemot tos vÄrÄ, un jau veikt kÄdas novÄrtÄÅ”anas, pamatojoties uz datu bÄzes pieaugumu, t.i., kÄ tÄ mums aug, ar kÄdu intensitÄti un jau veikt secinÄjumus par izmÄru optimizÄÅ”anu.

AktivitÄte rakstīŔanai. Kas ir ieraksts? ApskatÄ«sim operÄciju UPDATE ā rindu atjauninÄÅ”anas operÄcija tabulÄ. Faktiski update ir divas operÄcijas (vai pat vairÄk). TÄ ir jaunas rindas versijas ievietoÅ”ana un vecÄs rindas versijas atzÄ«mÄÅ”ana kÄ novecojusi. PÄc tam nÄks automÄtiska vakuuma operÄcija, un Ŕīs novecojuÅ”Äs rindas versijas tiks izdzÄstas, un Ŕī vieta tiks atzÄ«mÄta kÄ pieejama atkÄrtotai izmantoÅ”anai.
TurklÄt update nav tikai tabulas atjauninÄÅ”ana. Tas ir arÄ« indeksu atjauninÄÅ”ana. Ja jums tabulÄ ir daudz indeksu, tad, veicot update, visi indeksi, kuros piedalÄs laukÄ atjauninÄtie dati, arÄ« bÅ«s jÄpiedÄvÄ atjauninÄt. Å ajos indeksos arÄ« bÅ«s novecojuÅ”as rindas versijas, kuras bÅ«s jÄiztÄ«ra.

select
s.relname,
pg_size_pretty(pg_relation_size(relid)),
coalesce(n_tup_ins,0) + 2 * coalesce(n_tup_upd,0) -
coalesce(n_tup_hot_upd,0) + coalesce(n_tup_del,0) AS total_writes,
(coalesce(n_tup_hot_upd,0)::float * 100 / (case when n_tup_upd > 0
then n_tup_upd else 1 end)::float)::numeric(10,2) AS hot_rate,
(select v[1] FROM regexp_matches(reloptions::text,E'fillfactor=(\d+)') as
r(v) limit 1) AS fillfactor
from pg_stat_all_tables s
join pg_class c ON c.oid=relid
order by total_writes desc limit 50;Un pateicoties savai struktÅ«rai, UPDATE ir smagas operÄcijas. TomÄr tÄs var atvieglot. Ir hot updates. Tie parÄdÄ«jÄs PostgreSQL versijÄ 8.3. Un kas tas ir? Tas ir viegli atjauninÄms update, kas neizsauc indeksu pÄrveidoÅ”anu. T.i., mÄs atjaunojam ierakstu, bet tajÄ paÅ”Ä laikÄ tiek atjaunots tikai ieraksts lapÄ (kura pieder tabulai), bet indeksu pirms tam norÄdÄ«ja uz to paÅ”u ierakstu lapÄ. Tur nedaudz ir interesanta darba loÄ£ika, kad nÄk vakuums, tad tas Ŕīs saites hot pÄrveido un viss turpina darboties bez indeksu atjauninÄÅ”anas, un tas notiek ar mazÄkÄm resursu izmaksÄm.
Un kad jums ir n_tup_hot_upd liels, tas ir ļoti labi. Tas nozÄ«mÄ, ka vieglie atjauninÄjumi pÄrsniedz un tas veidojas mums lÄtÄk izmaksu ziÅÄ, un viss ir izcili.

ALTER TABLE table_name SET (fillfactor = 70);KÄ palielinÄt apjomu hot updateu? MÄs varam izmantot fillfactor. Tas nosaka rezervÄtÄ brÄ«vÄ vieta apjomu, kad tiek aizpildÄ«ta lapa tabulÄ ar INSERT. Kad tabulÄ tiek veiktas ievadīŔanas, tÄs pilnÄ«bÄ aizpilda lapu, neatstÄjot tajÄ tukÅ”u vietu. PÄc tam tiek pieŔķirta jauna lapa. Atkal dati tiek aizpildÄ«ti. Un Ŕī uzvedÄ«ba pÄc noklusÄjuma ir fillfactor = 100 %.
MÄs varam iestatÄ«t fillfactor uz 70%. T.i., kad tiek veiktas ievades, tiek izveidota jauna lapa, bet tiek aizpildÄ«ti tikai 70% lapas. Un 30% paliek rezerves. Kad bÅ«s nepiecieÅ”ams veikt atjauninÄjumu, ir ļoti liela varbÅ«tÄ«ba, ka tas notiks tajÄ paÅ”Ä lapÄ, un jaunÄ versija rindiÅas tiks ievietota tajÄ paÅ”Ä lapÄ. Tiks veikta hot_update. TÄdÄjÄdi tiek atvieglota ierakstīŔana tabulÄs.

select c.relname,
current_setting('autovacuum_vacuum_threshold') as av_base_thresh,
current_setting('autovacuum_vacuum_scale_factor') as av_scale_factor,
(current_setting('autovacuum_vacuum_threshold')::int +
(current_setting('autovacuum_vacuum_scale_factor')::float * c.reltuples))
as av_thresh,
s.n_dead_tup
from pg_stat_user_tables s join pg_class c ON s.relname = c.relname
where s.n_dead_tup > (current_setting('autovacuum_vacuum_threshold')::int
+ (current_setting('autovacuum_vacuum_scale_factor')::float * c.reltuples));Avotovakuuma rinda. Avotovakuums ir tÄda apakÅ”sistÄma, par kuru PostgreSQL statistikÄ ir ļoti maz informÄcijas. MÄs varam redzÄt tabulÄs tikai pg_stat_activity, cik daudz avotovakuuma paÅ”laik notiek. TomÄr saprast, cik daudz tabulu ir rinda, ir ļoti grÅ«ti.
PiezÄ«me: _SÄkot ar PostgreSQL versiju 10, situÄcija avotovakuuma uzraudzÄ«bÄ ir ievÄrojami uzlabojusies ā ir parÄdÄ«jusies pg_stat_progressvacuum, kas bÅ«tiski atvieglo avotovakuuma uzraudzÄ«bu.
MÄs varam izmantot Å”Ädu vienkÄrÅ”otu vaicÄjumu. Un mÄs varam paskatÄ«ties, kad vajadzÄtu veikt vakuumu. Bet kÄ un kad vajadzÄtu darboties vakuumam? Tie ir novecojuÅ”i rindiÅu varianti, par kuriem es runÄju iepriekÅ”. Tika veiktas atjauninÄjums, jauna rindiÅas versija tika ievietota. ParÄdÄ«jÄs novecojusi rindiÅas versija. TabulÄ pg_stat_user_tables ir tÄds parametrs n_dead_tup. Tas parÄda "miruÅ”o" rindiÅu skaitu. Un tiklÄ«dz miruÅ”o rindiÅu skaits kļūst lielÄks par noteiktu slieksni, avotovakuums ieradÄ«sies pie tabulas.
Un kÄ tiek aprÄÄ·inÄts Å”is slieksnis? Tas ir konkrÄts procentuÄlais attiecÄ«ba no kopÄjÄ rindiÅu skaita tabulÄ. Ir parametrs autovacuum_vacuum_scale_factor. Tas nosaka procentuÄlo attiecÄ«bu. PieÅemsim, 10% + tur klÄt ir 50 rindiÅu pamata slieksnis. Un kas notiek? Kad mums miruÅ”o rindiÅu skaits ir lielÄks par "10% + 50" no visÄm rindiÅÄm tabulÄ, mÄs iestatÄm tabulu uz avotovakuumu.

select c.relname,
current_setting('autovacuum_vacuum_threshold') as av_base_thresh,
current_setting('autovacuum_vacuum_scale_factor') as av_scale_factor,
(current_setting('autovacuum_vacuum_threshold')::int +
(current_setting('autovacuum_vacuum_scale_factor')::float * c.reltuples))
as av_thresh,
s.n_dead_tup
from pg_stat_user_tables s join pg_class c ON s.relname = c.relname
where s.n_dead_tup > (current_setting('autovacuum_vacuum_threshold')::int
+ (current_setting('autovacuum_vacuum_scale_factor')::float * c.reltuples));TomÄr te ir viens moments. Pamata slieksÅi parametriem av_base_thresh un av_scale_factor var varÄji noteikt individuÄli. Un attiecÄ«gi slieksnis nebÅ«s globÄls, bet individuÄls tabulai. TÄpÄc, lai aprÄÄ·inÄtu, tur jÄizmanto viltÄ«bas un triki. Un, ja jÅ«s interesÄ, varat apskatÄ«t mÅ«su kolÄÄ£u pieredzi no Avito (saite slaidÄ ir nederÄ«ga un atjauninÄta tekstÄ).
ViÅi uzrakstÄ«ja priekÅ” , kas Åem vÄrÄ Å”os faktorus. Tur ir divlapu garÅ” saraksts. Bet tas aprÄÄ·ina pareizi un diezgan efektÄ«vi ļauj novÄrtÄt, kur mums nepiecieÅ”ams daudz vakuuma tabulÄm, kur maz.
Ko mÄs ar to varam darÄ«t? Ja mums ir liela rinda un automÄtiskais vakuums netiek galÄ, mÄs varam palielinÄt vakuuma darbinieku skaitu vai vienkÄrÅ”i padarÄ«t vakuumu agresÄ«vÄku, lai tas tiktu aktivizÄts ÄtrÄk, apstrÄdÄjot tabulu mazÄkos gabalos. TÄdÄjÄdi rinda samazinÄsies. ā Galvenais ir uzraudzÄ«t slodzi uz diskdzinÄm, jo vakuums ir dÄrgs, lai gan ar SSD/NVMe ierÄ«Äu parÄdīŔanos Ŕī problÄma kļuva mazÄk pamanÄma.

Pg_stat_all_indexes ā tas ir statistikas rÄdÄ«tÄjs par indeksiem. Tas ir neliels. Un mÄs varam to izmantot, lai saÅemtu informÄciju par indeksu izmantoÅ”anu. Un piemÄram, varam noteikt, kuri indeksi mums ir lieki.

KÄ jau teicu, update ā tas ne tikai atjauno tabulas, tas arÄ« atjauno indeksus. AtbilstoÅ”i, ja mÅ«su tabulai ir daudz indeksu, tad, atjaunojot rindas tabulÄ, ir jÄtiek atjaunotiem arÄ« indeksÄtajiem laukiem, un ja mums ir neizmantoti indeksi, par kuriem nav indeksu skenÄÅ”anas, tad tie ir pÄrÄk smagi. Un no tiem ir jÄatbrÄ«vojas. TÄpÄc mums nepiecieÅ”ams lauks idx_scan. MÄs vienkÄrÅ”i skatÄmies indeksu skenÄÅ”anas skaitu. Ja indekss tam ir nulles skenÄÅ”ana relatÄ«vi garÄ statiskÄs informÄcijas uzglabÄÅ”anas periodÄ (ne mazÄk kÄ 2-3 nedÄļas), visticamÄk, tie ir sliktie indeksi, no kuriem mums jÄatbrÄ«vojas.
PiezÄ«me: MeklÄjot neizmantotus indeksus klasteru plÅ«stoÅ”Äs replikÄcijas gadÄ«jumÄ, ir jÄpÄrbauda visi klastera mezgli, jo statistika nav globÄla, un, ja indekss netiek izmantots uz galvenÄ, tas var tikt izmantots uz replikÄm (ja tur ir slodze).
Divas saites:
TÄs ir progresÄ«vÄkas pieprasÄ«jumu piemÄri, kÄ meklÄt neizmantotus indeksus.
OtrÄ saite ir diezgan interesants pieprasÄ«jums. Tur ir ļoti netipiska loÄ£ika. Ieteicu to iepazÄ«t.

Kas vÄl jÄpiezÄ«mÄ par indeksem?
Neizmantotie indeksi ir slikti.
ViÅi aizÅem vietu.
ViÅi palÄnina atjauninÄÅ”anas operÄcijas.
Liekas lieka darba vakumam.
Ja mÄs likvidÄsim neizmantotos indeksus, mÄs tikai uzlabosim datu bÄzi.

NÄkamais attÄlojums ir pg_stat_activity. Tas ir lÄ«dzÄ«gs rÄ«kam ps, tikai PostgreSQL. Ja ps'os jÅ«s skatÄties procesus operÄtÄjsistÄmÄ, tad pg_stat_activity tas parÄdÄ«s aktivitÄti iekÅ” PostgreSQL.
Ko mÄs varam noderÄ«gu iegÅ«t no turienes?

select
count(*)*100/(select current_setting('max_connections')::int)
from pg_stat_activity;MÄs varam aplÅ«kot kopÄjo aktivitÄti, kas notiek datu bÄzÄ. MÄs varam veikt jaunu izvietojumu. Mums tur viss ir sabojÄts, jauni savienojumi netiek pieÅemti, kļūdas krÄ«t aplikÄcijÄ.

select
client_addr, usename, datname, count(*)
from pg_stat_activity group by 1,2,3 order by 4 desc;MÄs varam izpildÄ«t Å”Ädu pieprasÄ«jumu un apskatÄ«t kopÄjo savienojumu procentu attiecÄ«bÄ pret maksimÄlo savienojumu limitu un redzÄt, kurÅ” no mums ir aizÅÄmis visvairÄk savienojumu. Un Å”ajÄ gadÄ«jumÄ mÄs redzam, ka lietotÄjs cron_role atvÄra 508 savienojumus. Un kaut kas ar viÅu tur notika. JÄrisina, jÄpÄrbauda. Un diezgan iespÄjams, ka tas ir kÄds anomÄls savienojumu skaits.

Ja mums ir OLTP slodze, pieprasÄ«jumiem jÄizpildÄs Ätri, ļoti Ätri, un nedrÄ«kst bÅ«t garu pieprasÄ«jumu. TomÄr, ja rodas gari pieprasÄ«jumi, tad Ä«stermiÅÄ nekas traks nav, bet ilgtermiÅÄ gari pieprasÄ«jumi kaitÄ datu bÄzei, tie palielina tabulu bloat efektu, kad notiek tabulu fragmentÄcija. No bloat un garu pieprasÄ«jumu jÄatbrÄ«vojas.

select
client_addr, usename, datname,
clock_timestamp() - xact_start as xact_age,
clock_timestamp() - query_start as query_age,
query
from pg_stat_activity order by xact_start, query_start;PievÄrsiet uzmanÄ«bu: ar Å”Ädu pieprasÄ«jumu mÄs varam noteikt garos pieprasÄ«jumus un darÄ«jumus. MÄs izmantojam funkciju clock_timestamp() lai noteiktu izpildes laiku. Garos pieprasÄ«jumus, kurus mÄs atradÄm, mÄs varam atcerÄties, izpildÄ«t explain, apskatÄ«t plÄnus un kaut kÄ optimizÄt. PaÅ”reizÄjos garos pieprasÄ«jumus mÄs iznÄ«cinÄm un turpinÄm dzÄ«vot.

select * from pg_stat_activity where state in
('idle in transaction', 'idle in transaction (aborted)';Slikti darÄ«jumi ir darÄ«jumi stÄvoklÄ« idle in transaction un idle in transaction (aborted).
Ko tas nozÄ«mÄ? TranzakcijÄm ir vairÄkas stÄvokļa situÄcijas. Un viens no Å”iem stÄvokļiem var mainÄ«ties jebkurÄ brÄ«dÄ«. Lai noteiktu stÄvokļus, ir lauks state Å”ajÄ skatÄ«jumÄ. Un mÄs to izmantojam, lai noteiktu stÄvokli.

select * from pg_stat_activity where state in
('idle in transaction', 'idle in transaction (aborted)';Un, kÄ jau iepriekÅ” minÄju, Å”ie divi stÄvokļi idle in transaction un idle in transaction (aborted) ā tas ir slikti. Kas tas ir? Tas ir tad, kad pielietojums ir atvÄris tranzakciju, veicis kÄdas darbÄ«bas un devies savÄs lietÄs. Tranzakcija ir palikusi atvÄrta. TÄ karÄjas, tajÄ nekas nenotiek, tÄ aizÅem savienojumu, bloÄ·Ä modificÄtÄs rindas un potenciÄli vÄl palielina bloat citu tabulu dÄļ, pateicoties Postgres tranzakciju dzinÄja arhitektÅ«rai. Un Å”Ädas tranzakcijas arÄ« ir jÄnovÄrÅ”, jo tÄs ir kaitÄ«gas visÄs jomÄs.
Ja jÅ«s redzat, ka jÅ«su datu bÄzÄ ir vairÄk par 5-10-20, tad jÄsÄk uztraukties un kaut kas ir jÄdara.
Å eit mÄs arÄ« laika aprÄÄ·inam izmantojam clock_timestamp(). Tranzakcijas novÄrÅ”am, pielietojumu optimizÄjam.

KÄ jau iepriekÅ” minÄju, bloÄ·ÄÅ”ana ā tas ir tad, kad divas vai vairÄk tranzakcijas cÄ«nÄs par vienu vai grupu resursu. TÄpÄc mums ir lauks waiting ar loÄ£isko vÄrtÄ«bu true vai false.
True ā tas nozÄ«mÄ, ka process ir gaidīŔanas režīmÄ, jÄveic kaut kas. Kad process ir gaidīŔanas režīmÄ, tas nozÄ«mÄ, ka klients, kurÅ” iniciÄjis Å”o procesu, arÄ« gaida. Klients pÄrlÅ«kprogrammÄ arÄ« sÄž un gaida.
UzmanÄ«bu: _SÄkot no Postgres 9.6 versijas, lauks waiting ir dzÄsts un tÄ vietÄ ir pievienoti divi informatÄ«vÄki lauki wait_event_type un wait_event._

Ko darÄ«t? Ja jÅ«s redzat true ilgu laiku, tas nozÄ«mÄ, ka no Å”Ädiem pieprasÄ«jumiem jÄatbrÄ«vojas. MÄs vienkÄrÅ”i novÄrÅ”am Å”Ädas tranzakcijas. ProgrammatÅ«ras izstrÄdÄtÄjiem informÄjam, ka kaut kÄ jÄoptimizÄ, lai nebÅ«tu resursu konkurences. Un turpinÄjumÄ izstrÄdÄtÄji optimizÄ lietotni, lai Å”Ädas situÄcijas neradÄ«tos.
Un pÄdÄjais, bet potenciÄli ne fatÄls gadÄ«jums ā tas ir deadlocks raÅ”anÄs. Divas tranzakcijas atjauninÄja divus resursus, pÄc tam atkal piekļūst tiem, jau pretÄjiem resursiem. PostgreSQL Å”ajÄ gadÄ«jumÄ paÅems un pats novÄrsÄ«s tranzakciju, lai cita varÄtu turpinÄt darbu. TÄ ir slÄgta situÄcija, un tÄ pati nesakÄrtosies. TÄpÄc PostgreSQL ir spiests pieÅemt galÄjus pasÄkumus.

Un Å”eit ir divi pieprasÄ«jumi, kas ļauj izsekot bloÄ·ÄÅ”anÄm. MÄs izmantojam skatu pg_locks, kas ļauj izsekot smagas bloÄ·ÄÅ”anas.
Un pirmais saite ā tas ir pats jautÄjuma teksts. Tas ir diezgan garÅ”.
Un otra saite ā tas ir raksts par bloÄ·ÄÅ”anÄm. To ir lietderÄ«gi izlasÄ«t, tas ir ļoti interesants.
TÄtad, ko mÄs redzam? MÄs redzam divus pieprasÄ«jumus. Transakcija ar ALTER TABLE ā tas ir bloÄ·ÄjoÅ”s transakcija. TÄ ir uzsÄkta, bet nav pabeigta, un lietojumprogramma, kas uzsÄka Å”o transakciju, kaut kur nodarbojas ar citÄm lietÄm. Un otrais pieprasÄ«jums ā update. Tas gaida, kad pabeigsies alter table, lai varÄtu turpinÄt savu darbu.
TÄlÄk mÄs varam noskaidrot, kurÅ” kÄdu ir aizÄ·Äris, tur un varam ar to strÄdÄt tÄlÄk.

NÄkamais modulis ā tas ir pg_stat_statements. KÄ jau teicu, tas ir modulis. Lai to izmantotu, ir jÄielÄdÄ tÄ bibliotÄka konfigurÄcijÄ, jÄpÄrstartÄ PostgreSQL, jÄinstalÄ modulis (vienÄ komandÄ) un tad mums parÄdÄ«sies jauns skatÄ«jums.

VidÄjais pieprasÄ«juma laiks milisekundÄs
$ select (sum(total_time) / sum(calls))::numeric(6,3)
from pg_stat_statements;
VisaktÄ«vÄkie rakstīŔanas pieprasÄ«jumi (shared_buffers)
$ select query, shared_blks_dirtied
from pg_stat_statements
where shared_blks_dirtied > 0 order by 2 desc;Ko mÄs varam no turienes Åemt? Ja runÄjam par vienkÄrÅ”Äm lietÄm, mÄs varam Åemt vidÄjo pieprasÄ«juma izpildes laiku. Ja laiks pieaug, tas nozÄ«mÄ, ka PostgreSQL atbild lÄni, un mums jÄveic kÄdi pasÄkumi.
MÄs varam aplÅ«kot visaktÄ«vÄkÄs rakstīŔanas transakcijas datu bÄzÄ, kas maina datus shared buffers. AplÅ«kot, kas mums tur atjaunina vai dzÄÅ” datus.
Un mÄs varam vienkÄrÅ”i aplÅ«kot dažÄdu statistiku par Å”iem pieprasÄ«jumiem.

MÄs pg_stat_statements izmantojam ziÅojumu veidoÅ”anai. Reizi dienÄ atiestatÄm statistiku. UzkrÄjam to. Pirms nÄkamÄs statistikas atiestatīŔanas veidojam ziÅojumu. Å eit ir saite uz ziÅojumu. JÅ«s to varat apskatÄ«t.

Ko mÄs darÄm? MÄs saskaitÄm kopÄjo statistiku par visiem pieprasÄ«jumiem. PÄc tam katram pieprasÄ«jumam mÄs aprÄÄ·inÄm tÄ individuÄlo ieguldÄ«jumu Å”ajÄ kopÄjÄ statistikÄ.
Un ko mÄs varam aplÅ«kot? MÄs varam aplÅ«kot kopÄjo visu konkrÄta veida pieprasÄ«jumu izpildes laiku pret visiem pÄrÄjiem pieprasÄ«jumiem. MÄs varam aplÅ«kot procesora un ievades-izejas resursu izmantoÅ”anu attiecÄ«bÄ pret kopÄjo ainu. Un pÄc tam optimizÄt Å”os pieprasÄ«jumus. MÄs veidojam TOP pieprasÄ«jumus pÄc Ŕī ziÅojuma un jau saÅemam ierosinÄjumu tam, kas jÄoptimizÄ.

Ko mums ir atliek no kadra? Ir palikuÅ”as vÄl dažas prezentÄcijas, kuras es neapskatÄ«ju, jo laiks ir ierobežots.
Ir pgstattuple ā tas ir arÄ« papildu modulis no standarta pakas contribs. Tas ļauj novÄrtÄt bloat tabulas, t.s. tabulu fragmentÄciju. Un, ja fragmentÄcija ir liela, to nepiecieÅ”ams novÄrst, izmantojot dažÄdus rÄ«kus. Un funkcija pgstattuple strÄdÄ ilgstoÅ”i. Un, jo vairÄk ir tabulu, jo ilgÄk tÄ strÄdÄs.

NÄkamais contrib ā tas ir pg_buffercache. Tas ļauj veikt pÄrbaudi shared buffers: cik intensÄ«vi un uz kurÄm tabulÄm tiek izmantotas buferu lapas. Un vienkÄrÅ”i ļauj ieskatÄ«ties shared buffers un novÄrtÄt, kas tur notiek.
NÄkamais modulis ā tas ir pgfincore. Tas ļauj veikt zema lÄ«meÅa operÄcijas ar tabulÄm, izmantojot sistÄmas izsaukumu mincore(), t.i., tas ļauj ielÄdÄt tabulu shared buffers, vai to izsist. Un, starp citu, ļauj veikt operÄciju sistÄmas lapu keÅ”atmiÅas pÄrbaudi, t.i., kÄdÄ apjomÄ mÅ«su tabula aizÅem page cache, shared buffers un vienkÄrÅ”i ļauj novÄrtÄt tabulas noslogojumu.
NÄkamais modulis ā pg_stat_kcache. Tas arÄ« izmanto sistÄmas izsaukumu getrusage(). Un veic to pirms un pÄc vaicÄjuma izpildes. Un iegÅ«tajÄ statistikÄ Ä¼auj novÄrtÄt, cik daudz mÅ«su vaicÄjums ir tÄrÄjis uz diska I/O veikÅ”anu, t.i., operÄcijÄm ar failu sistÄmu, un skatÄs, kÄ tiek izmantots procesors. TomÄr modulis ir jauns (khem-khem) un tÄ darbÄ«bai nepiecieÅ”ams PostgreSQL 9.4 un pg_stat_statements, par ko es runÄju iepriekÅ”.

SpÄja izmantot statistiku ā ir noderÄ«ga. Jums nav nepiecieÅ”amas treÅ”o puÅ”u programmas. JÅ«s varat pats ieskatÄ«ties, apskatÄ«t, kaut ko izdarÄ«t, veikt.
Izmantot statistiku nav grÅ«ti, tas ir parasts SQL. JÅ«s esat savÄkuÅ”i vaicÄjumu, sastÄdÄ«juÅ”i, nosÅ«tÄ«juÅ”i, apskatÄ«juÅ”i.
Statistika palÄ«dz atbildÄt uz jautÄjumiem. Ja jums rodas jautÄjumi, jÅ«s vÄrÅ”aties pie statistikas ā skatÄties, izdarÄt secinÄjumus, analizÄjat rezultÄtus.
Un eksperimentÄjiet. Ir daudz vaicÄjumu, daudz datu. VienmÄr var optimizÄt kÄdu jau esoÅ”u vaicÄjumu. Var izveidot savu versiju vaicÄjuma, kas jums ir piemÄrotÄka nekÄ oriÄ£inÄls, un izmantot to.

Saites
DroÅ”as saites, kas tika minÄtas rakstÄ, kurÄ bija materiÄli, kas tika izmantoti ziÅojumÄ.
Autors raksta vÄl
(eng)
Statistikas kolektors
SistÄmas administrÄÅ”anas funkcijas
Contrib moduļi
SQL rÄ«ki un SQL koda piemÄri
Paldies visiem par uzmanību!
Avots: habr.com
