{"id":81089,"date":"2020-05-11T01:42:24","date_gmt":"2020-05-10T23:42:24","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov"},"modified":"2020-05-11T01:42:24","modified_gmt":"2020-05-10T23:42:24","slug":"tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov","status":"publish","type":"post","link":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov","title":{"rendered":"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><strong>Predla\u017eem da se upoznate s transkripcijom izlaganja Andreja Salnikova iz po\u010detka 2016. godine \"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u\"<\/strong><\/p>\n<p><\/p>\n<p>U ovom izlaganju \u0107u obraditi osnovne gre\u0161ke u aplikacijama koje se javljaju u fazi projektiranja i pisanja aplikativnog koda. Fokusira\u0107u se samo na one gre\u0161ke koje dovode do bloat-a u PostgreSQL-u. Obi\u010dno to ozna\u010dava po\u010detak kraja performansi va\u0161eg sistema u celini, iako na prvi pogled nisu postojale nikakve naznake za to.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/a9e199bfe2e01c76966b32868790f8f0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Drago mi je da vas sve pozdravim! Ovo izlaganje nije toliko tehni\u010dko kao prethodno od mog kolege. Ovo izlaganje je prvenstveno usmereno na razvijatelje backend sistema, jer imamo dosta klijenata. I svi oni prave iste gre\u0161ke. O tome \u0107u vam pri\u010dati. Objasni\u0107u vam do kakvih katastrofalnih i lo\u0161ih posledica vode te gre\u0161ke. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/c6c84dbafc595ae3068cd8bf804ccee7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Za\u0161to se gre\u0161ke doga\u0111aju? Doga\u0111aju se iz dva razloga: zbog neodgovornog pristupa, nadaju\u0107i se da \u0107e to mo\u017eda pro\u0107i, i zbog nepoznavanja mehanizama koji se odvijaju na nivoima izme\u0111u baze podataka i aplikacije, kao i unutar same baze. <\/p>\n<p><\/p>\n<p>Pokaza\u0107u vam tri primera s groznim slikama o tome kako je sve postalo lo\u0161e. Ukratko \u0107u objasniti mehanizam koji se doga\u0111a. I kako se boriti protiv tih problema kada se dogode, kao i koje preventivne metode koristiti za spre\u010davanje gre\u0161aka. Govori\u0107u o pomo\u0107nim alatima i dati korisne linkove. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/b0230d992f5b44f0e542df2e4b4d526f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Koristio sam testnu bazu podataka, gde sam imao dve tabele. Jedna tabela je sa ra\u010dunima klijenata, druga s operacijama na tim ra\u010dunima. S vremena na vreme a\u017euriramo stanje na tim ra\u010dunima.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/1d2a21278b095b07546e1bb870819dbf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Izvorni podaci tabele: ona je dovoljno mala, 2 MB. Vreme odgovora za bazu i konkretno za tu tabelu je tako\u0111e vrlo dobro. Dobar je i pritisak \u2013 2000 operacija u sekundi na tabeli.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/dea5a4b1ac7952f8cfed0e2e1cfc10dd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kroz ovo izlaganje \u0107u vam prikazati grafike kako bi bilo jasno \u0161ta se doga\u0111a. Uvek \u0107e biti 2 slajda s grafikonima. Prvi slajd \u2013 to je ono \u0161to se doga\u0111a u op\u0161tem smislu na serveru. <\/p>\n<p><\/p>\n<p>U ovoj situaciji vidimo da imamo tabelu male veli\u010dine. Indeks je mali, 2 MB. To je prvi graf s leve strane. <\/p>\n<p><\/p>\n<p>Prose\u010dno vreme odgovora na serveru tako\u0111e je stabilno i malo. To je gornji desni graf. <\/p>\n<p><\/p>\n<p>Donji lijevi grafikon prikazuje najdulje transakcije. Vidimo da se transakcije brzo izvr\u0161avaju. I automatska vakuum funkcija jo\u0161 nije aktivna, jer je ovo bio testni start. U budu\u0107nosti \u0107e raditi i bit \u0107e nam koristan.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/9e9b46acd9a878ff70ca4a7850adff09.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Drugi slajd uvijek \u0107e biti posve\u0107en ispitivanoj tablici. U ovoj situaciji neprekidno a\u017euriramo zalihe na ra\u010dunima klijenta. I vidimo da je prosje\u010dno vrijeme odziva za operaciju a\u017euriranja prili\u010dno dobro, manje od milisekunde. Primje\u0107ujemo tako\u0111er da resursi procesora (to je gornji desni grafikon) tako\u0111er ravnomjerno tro\u0161e i to na razmjerno maloj razini. <\/p>\n<p><\/p>\n<p>Gornji desni grafikon pokazuje koliko operativne i diskovne memorije koristimo u potrazi za potrebnim redom, prije nego \u0161to ga a\u017euriramo. Broj operacija po tablici je 2,000 u sekundi, kao \u0161to sam spomenuo na po\u010detku. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/84760d52716209b8dcfffb462c67a8e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>A sada se doga\u0111a tragedija. Iz nekog razloga javlja se duga zaboravljena transakcija. Razlozi su obi\u010dno prozai\u010dni: <\/p>\n<p><\/p>\n<ul>\n<li>Jedan od naj\u010de\u0161\u0107ih razloga je taj \u0161to smo u kodu aplikacije po\u010deli obra\u0107ati se vanjskom servisu. I taj servis nam ne odgovara. To jest, otvorili smo transakciju, promijenili bazu i oti\u0161li \u010ditati po\u0161tu ili se obratili drugom servisu unutar na\u0161e infrastrukture, koji nam iz nekog razloga ne odgovara. I imamo zaklju\u010danu sesiju u stanju - ne zna se kada \u0107e se razrije\u0161iti.<\/li>\n<li>Druga situacija nastaje kada je u na\u0161em kodu iz nekog razloga do\u0161lo do iznimke. I u iznimci nismo obradili zatvaranje transakcije. Tako da imamo visoko stanje sesije s otvorenom transakcijom. <\/li>\n<li>I posljednji - to je tako\u0111er prili\u010dno \u010dest slu\u010daj. To je nekvalitetan kod. Neki okviri otvaraju transakciju. Ona visi, a mo\u017eete u aplikaciji ne znati da ona visi. <\/li>\n<\/ul>\n<p><\/p>\n<p>K \u010demu dovode ovakve stvari? <\/p>\n<p><\/p>\n<p>Do toga da se na\u0161e tablice i indeksi po\u010dinju naglo pove\u0107avati. Ovo je to\u010dno taj efekt bloat. Za bazu to \u0107e zna\u010diti da \u0107e se vrlo naglo pove\u0107ati vrijeme odgovora baze podataka, pove\u0107at \u0107e se optere\u0107enje na serveru baze podataka. I kao rezultat toga, na\u0161e \u0107e aplikacije trpjeti. Jer ako ste u kodu tro\u0161ili 10 milisekundi na upit u bazu, 10 milisekundi na svoju logiku, tada je va\u0161a funkcija radila 20 milisekundi. A sada \u0107e va\u0161a situacija biti potpuno tu\u017ena. <\/p>\n<p><\/p>\n<p>Pogledajmo \u0161to se doga\u0111a. Donji lijevi grafikon pokazuje da imamo dugotrajnu transakciju. Ako pogledamo gornji lijevi grafikon, vidimo da je veli\u010dina tablice s dva megabajta naglo porasla na 300 megabajta. Pri tome se broj podataka u tablici nije promijenio, tj. u njoj se nalazi prili\u010dno velika koli\u010dina otpada.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/b1947f6487e440a770a1251a955e62d2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Sveukupna situacija po srednjem vremenu odgovora poslu\u017eitelja tako\u0111er se promijenila na nekoliko redova veli\u010dine. Dakle, svi upiti prema poslu\u017eitelju po\u010deli su drasti\u010dno usporavati. U me\u0111uvremenu, pokrenuli su se unutarnji procesi Postgresa u obliku automatske vakuumacije, koji poku\u0161avaju ne\u0161to u\u010diniti i tro\u0161e resurse.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/8e91f035d1dd04e72e842d714cc611a5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u0160to se doga\u0111a s na\u0161om tablicom? Ista stvar. Prosje\u010dno vrijeme odgovora na tablicu naglo je poraslo. Ako govorimo o potro\u0161nji resursa, vidimo da je optere\u0107enje procesora znatno pove\u0107ano. To je na gornjem desnom grafikonu. Pove\u0107ano je zato \u0161to procesor mora pregledavati hrpu beskorisnih redaka u potrazi za jednim potrebnim. To je na donjem desnom grafikonu. Kao rezultat, broj poziva po sekundi po\u010deo je naglo opadati, jer baza ne uspijeva obraditi isti broj upita. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/424685ce852bc5f3ef77151f8d3d7289.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Moramo se vratiti u \u017eivot. Ulazimo na internet i saznajemo da dugotrajne transakcije dovode do problema. Nalazimo i ubijamo tu transakciju. I sve se vra\u0107a u normalu. Sve radi kako treba. <\/p>\n<p><\/p>\n<p>Smirili smo se, ali nakon nekog vremena po\u010dinjemo primje\u0107ivati da aplikacija ne radi kako je radila prije incidenta. Upiti se i dalje obra\u0111uju sporije, i to zna\u010dajno sporije. U mom slu\u010daju, oko jedan i pol do dva puta sporije. Optere\u0107enje na poslu\u017eitelju tako\u0111er je ve\u0107e nego \u0161to je bilo prije incidenta. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/ee3037719a31f8d18fc42745716c4da5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pitanje je: \"\u0160to se doga\u0111a s bazom u tom trenutku?\" A u bazi se doga\u0111a sljede\u0107a situacija. Na grafikonu transakcija vidite da je stala i doista nema dugotrajnih transakcija. No veli\u010dine tablice tijekom incidenta su katastrofalno narasle. I od tada se nisu smanjile. Prosje\u010dno vrijeme u bazi se stabiliziralo. Odgovori izgledaju razmjerno normalno s prihvatljivom brzinom za nas. Automatska vakuumacija postala je aktivnija i po\u010dela je ne\u0161to raditi s tablicom jer mora obraditi ve\u0107u koli\u010dinu podataka. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/f6205242c4024dc3ed4cade5844dbf76.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Specifi\u010dno za testiranu tablicu s ra\u010dunima, gdje mijenjamo ostatke: vrijeme odgovora na upit \u010dini se da se vratilo u normalu. No, zapravo je 1,5 puta vi\u0161e.<\/p>\n<p><\/p>\n<p>I po optere\u0107enju na procesoru vidimo da optere\u0107enje na procesoru nije dosegnulo potrebnu razinu do incidenta. Razlozi su upravo u donjem desnom grafikonu. Vidljivo je da se ondje doga\u0111a prekomjerna upotreba nekih resursa memorije. Dakle, za pronala\u017eenje potrebnog retka tro\u0161imo server resurse baze podataka pretra\u017euju\u0107i beskorisne podatke. Broj transakcija u sekundi se stabilizirao. <\/p>\n<p><\/p>\n<p>Op\u0107enito dobro, ali situacija je gora nego prije. O\u010dita degradacija baze podataka kao posljedica na\u0161e aplikacije koja radi s tom bazom podataka. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/0dfc9cd453fd84bc639ffd99cf189fd2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I kako bismo razumjeli \u0161to se doga\u0111a, ako niste bili na prethodnom izlaganju, malo teorije. Teorija o unutarnjem procesu. Za\u0161to je automatska vakuumacija potrebna i \u0161to ona radi?<\/p>\n<p><\/p>\n<p>Ukratko, za razumijevanje. U jednom trenutku imamo tablicu. U tablici imamo retke. Ti retci mogu biti aktivni, \u017eivi, potrebni nam sada. Na slici su ozna\u010deni zelenom bojom. A postoje mrtvi retci, koji su ve\u0107 obra\u0111eni, a\u017eurirani, na njima su nastale nove stavke. I oni su ozna\u010deni da vi\u0161e nisu zanimljivi bazi podataka. No, ostaju u tablici zbog posebnosti Postgres-a.<\/p>\n<p><\/p>\n<p>Za\u0161to je potrebna automatska vakuumacija? Automatska vakuumacija u nekom trenutku dolazi, obra\u0107a se bazi podataka i pita je: \"Daj mi, molim te, ID najstarije transakcije koja je trenutno otvorena u bazi podataka.\" Baza podataka vra\u0107a taj ID. A automatska vakuumacija, oslanjaju\u0107i se na njega, prolazi kroz retke u tablici. Ako vidi da su neki retci izmijenjeni mnogo starijim transakcijama, onda ima pravo ozna\u010diti ih kao retke koje mo\u017eemo ponovno koristiti u budu\u0107nosti, zapisuju\u0107i nove podatke. To je pozadinski proces.<\/p>\n<p><\/p>\n<p>U tom trenutku nastavljamo raditi s bazom podataka, nastavljamo vr\u0161iti neke promjene u tablici. I na te retke koje mo\u017eemo ponovno koristiti, zapisujemo nove podatke. Tako da imamo kru\u017enu ekonomiju, tj. stalno se pojavljuju neki stari mrtvi retci, umjesto njih zapisujemo nove retce koji su nam potrebni. I to je normalno stanje za rad PostgreSQL-a.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/98dd4451a7ca5f418775f72822c2840c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u0160to se dogodilo tijekom nesre\u0107e? Kako je taj proces tekao?<\/p>\n<p><\/p>\n<p>Imali smo tablicu u nekom stanju, neki su redovi bili aktivni, neki ne. Do\u0161ao je autotvacuum. Pitao je bazu podataka koja je na\u0161a najstarija transakcija i koji joj je ID. Dobio je taj ID, koji mo\u017ee biti star nekoliko sati ili nekoliko minuta. To ovisi o tome koliki je pritisak na va\u0161oj bazi podataka. I onda je krenuo tra\u017eiti redove koje mo\u017ee ozna\u010diti kao ponovno upotrebljive. I nije prona\u0161ao takve redove u na\u0161oj tablici. <\/p>\n<p><\/p>\n<p>Ali mi u tom trenutku nastavljamo raditi s tablicom. Radimo ne\u0161to, a\u017euriramo, mijenjamo podatke. A \u0161to baza podataka u to vrijeme radi? Nema joj druge nego dodavati nove redove na kraj postoje\u0107e tablice. Tako da nam se veli\u010dina tablice po\u010dinje pove\u0107avati. <\/p>\n<p><\/p>\n<p>U stvarnosti su nam potrebni zeleni redovi za rad. Ali tijekom takvih problema dobivamo da je postotak zelenih redova izuzetno nizak u cijelom volumenu tablice. <\/p>\n<p><\/p>\n<p>Kada izvr\u0161avamo upit, bazi podataka treba pro\u0107i kroz sve redove: i crvene i zelene, da prona\u0111e potrebni red. Efekt pove\u0107anja tablice beskorisnim podacima naziva se \u201ebloat\u201c, koji tako\u0111er tro\u0161i na\u0161 prostor na disku. Sje\u0107ate se, bilo je 2 MB, postalo je 300 MB? A sada zamijenite megabajte gigabajtima i brzo \u0107ete izgubiti sve svoje diskovne resurse.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/fe7cb6b5c99610744ebcfe5ad7235d1e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Koje posljedice mogu biti za nas? <\/p>\n<p><\/p>\n<ul>\n<li>U mom primjeru, tablica i indeks su narasli 150 puta. Neki od na\u0161ih klijenata su imali jo\u0161 te\u017ee situacije kada bi prostor na disku po\u010deo ponestajati. <\/li>\n<li>Veli\u010dina tablica sama po sebi nikada ne\u0107e opasti. Autovacuum ponekad mo\u017ee odrezati rep tablice ako su tu samo mrtvi redovi. No, budu\u0107i da se stalno doga\u0111a rotacija, jedan zeleni red mo\u017ee zape\u0107i na kraju i ne a\u017eurirati se, dok \u0107e svi ostali biti upisani negdje na po\u010detku tablice. No, to je toliko malo vjerojatno da \u0107e se va\u0161a tablica smanjiti, tako da nije realno o\u010dekivati. <\/li>\n<li>Bazi podataka treba pro\u0107i kroz cijeli niz beskorisnih redova. Tro\u0161imo diskovne resurse, tro\u0161imo resurse procesora i energiju. <\/li>\n<li>I to izravno utje\u010de na na\u0161u aplikaciju, jer ako smo na po\u010detku tro\u0161ili 10 milisekundi na upit, 10 milisekundi na na\u0161 kod, tijekom akcidenta smo po\u010deli tro\u0161iti sekundu na upit i 10 milisekundi na kod, tj. performanse aplikacije su se smanjile red veli\u010dine. A kada je akcident otklonjen, po\u010deli smo tro\u0161iti 20 milisekundi na upit i 10 milisekundi na kod. To zna\u010di da smo ipak pali 1,5 puta u performansama. I to sve zbog jedne transakcije koja je zapela, mo\u017eda \u010dak i zbog na\u0161e pogre\u0161ke. <\/li>\n<li>I pitanje je: \u201eKako sve vratiti natrag?\u201c, da se sve vrati u normalu i da upiti budu jednako brzi kao prije incidenta. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/1bf46e8cd9b28ca2862f978f2ca85819.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Za to postoji odre\u0111eni ciklus radnji koji se provodi. <\/p>\n<p><\/p>\n<p>Prvo, potrebno je prona\u0107i problemati\u010dne tablice koje su se pro\u0161irile. Shva\u0107amo da se za neke tablice zapisivanje odvija aktivnije, dok se za neke odvija manje aktivno. I za to se koristi pro\u0161irenje <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/pgstattuple.html\">pgstattuple<\/a><\/noindex>. Instaliranjem ovog pro\u0161irenja mo\u017eete napisati upite koji \u0107e vam pomo\u0107i prona\u0107i tablice koje su se zna\u010dajno pro\u0161irile. <\/p>\n<p><\/p>\n<p>Nakon \u0161to prona\u0111ete te tablice, potrebno ih je sa\u017eeti. Za to postoje alati. U na\u0161oj tvrtki koristimo tri alata. Prvi je ugra\u0111eni VACUUM FULL. On je nemilosrdan, strog i surov, ali ponekad je vrlo koristan. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">Pg_repack<\/a><\/noindex> i <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">pgcompacttable<\/a><\/noindex> \u2013 to su vanjski alati za sa\u017eimanje tablica. I oni se vi\u0161e brinu o bazi podataka. <\/p>\n<p><\/p>\n<p>Koriste se ovisno o tome \u0161to vam vi\u0161e odgovara. No, o tome \u0107u govoriti na kraju. Glavno je da postoje tri alata. Ima izbora. <\/p>\n<p><\/p>\n<p>Nakon \u0161to smo sve ispravili, osigurali se da je sve dobro, moramo znati kako sprije\u010diti ovu situaciju u budu\u0107nosti:<\/p>\n<p><\/p>\n<ul>\n<li>Sprje\u010dava se relativno lako. Potrebno je pratiti trajanje sesija na Master serveru. <strong>Posebno opasne sesije su one u stanju idle in transaction<\/strong>. To su one koje su otvorile transakciju, ne\u0161to napravile i oti\u0161le ili su jednostavno zapela, izgubila se u kodu. <\/li>\n<li>I za vas, kao programere, va\u017eno je testirati kod na trenutak nastanka ovih situacija. To nije te\u0161ko u\u010diniti. To \u0107e biti korisna provjera. Izbje\u0107i \u0107ete veliki broj \"dje\u010djih\" problema povezanih s dugim transakcijama. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/d55465d96c4018db733954867d23aaba.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Na ovim grafikonima \u017eelim vam pokazati kako se promijenila tablica i pona\u0161anje baze podataka nakon \u0161to sam u ovom slu\u010daju izvr\u0161io VACUUM FULL na tablici. To nije proizvodnja.<\/p>\n<p><\/p>\n<p>Veli\u010dina tablice odmah se vratila u normalno radno stanje od nekoliko megabajta. Na prosje\u010dno vrijeme odgovora na serveru to nije imalo velikog utjecaja. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/cbb07ad24dba899395223d1ca25e438e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>No, konkretno po na\u0161oj ispitu tablici, gdje smo a\u017eurirali stanje na ra\u010dunima, vidimo da se prosje\u010dno vrijeme odgovora na zahtjev za a\u017euriranjem podataka u tablici smanjilo na prekriznu razinu. Resursi koje procesor tro\u0161i za izvr\u0161avanje ovog zahtjeva tako\u0111er su pali na prekriznu razinu. A donji desni grafikon pokazuje da sada nalazimo upravo onaj red koji nam treba odmah, bez pretra\u017eivanja hrpe mrtvih redova koji su postojali prije kompresije tablice. I prosje\u010dno vrijeme zahtjeva ostalo je otprilike na istoj razini. No, tu imam vi\u0161e gre\u0161ku u svom hardveru.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/c1d90c5442e02fce209dc40e048a8ca2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ovdje zavr\u0161ava prva pri\u010da. To je naj\u010de\u0161\u0107a pri\u010da. I doga\u0111a se svima, bez obzira na iskustvo klijenta, koliko su tamo kvalificirani programeri. Pr sooner ili kasnije to se dogodi. <\/p>\n<p><\/p>\n<p>Druga pri\u010da, u kojoj raspore\u0111ujemo optere\u0107enje i optimiziramo servere.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/cda421c554d1329107ddc935045cc1b9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<ul>\n<li>Ve\u0107 smo odrasli i postali ozbiljni de\u010dki. I shva\u0107amo da imamo replikaciju i dobro bi nam do\u0161lo da uravnote\u017eimo optere\u0107enje: pisati na Master, a \u010ditati s replike. Obi\u010dno ova situacija nastaje kada \u017eelimo pripremati izvje\u0161taje ili ETL. I poslovanje je tome jako zadovoljno. Jako \u017eeli razne izvje\u0161taje s hrpom slo\u017eene analitike. <\/li>\n<li>Izvje\u0161taji traju satima, jer se slo\u017eena analitika ne mo\u017ee izra\u010dunati u milisekundama. Kao hrabri de\u010dki, pi\u0161emo kod. U aplikaciji pravimo umetanja, tako da zapisujemo na Master, a izvje\u0161taje izvr\u0161avamo na repliki. <\/li>\n<li>Raspore\u0111ujemo optere\u0107enje. <\/li>\n<li>Sve radi odli\u010dno. Mi smo odli\u010dni. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/e94c8c492197a5015ac8aae79389a4c2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kako ta situacija izgleda? Konkretno na ovim grafikonima dodao sam trajanje transakcija s replike. Svi ostali grafikon odnosni su samo na Master server. <\/p>\n<p><\/p>\n<p>Izvje\u0161tajna tablica sada je postala ve\u0107a. Ima ih vi\u0161e. Vidimo da je prosje\u010dno vrijeme odgovora poslu\u017eitelja stabilno. Primje\u0107ujemo da imamo dugotrajnu transakciju na replici koja traje 2 sata. Vidimo miran rad automatskog vakuuma koji obra\u0111uje mrtve redove. I sve je u redu. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/2da8acf098d12d6f146ab9b9dcb54b81.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Specifi\u010dno za testiranu tablicu nastavljamo a\u017eurirati salda na ra\u010dunima. Tako\u0111er imamo stabilno vrijeme odgovora na zahtjeve, stabilnu potro\u0161nju resursa. Sve je u redu. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/3621ef723017bac6fb635caf0a5f4de6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Sve je dobro dok se ti izvje\u0161taji ne po\u010dnu ispaljivati zbog sukoba s replikacijom. I ispaljuju se s konstantnom u\u010destalo\u0161\u0107u. <\/p>\n<p><\/p>\n<p>Pretra\u017eujemo internet i po\u010dinjemo \u010ditati za\u0161to se to doga\u0111a. Pronalazimo rje\u0161enja. <\/p>\n<p><\/p>\n<p>Prvo rje\u0161enje je pove\u0107ati ka\u0161njenje replikacije. Znamo da na\u0161 izvje\u0161taj radi 3 sata. Postavljamo ka\u0161njenje replikacije na 3 sata. Pokre\u0107emo sve, ali problemi s izvje\u0161tajima i dalje traju. <\/p>\n<p><\/p>\n<p>\u017delimo da sve bude savr\u0161eno. Idemo dalje. I nalazimo izvrsnu postavku na internetu \u2013 hot_standby_feedback. Uklju\u010dujemo ga. Hot_standby_feedback nam omogu\u0107uje da zadr\u017eimo rad automatskog vakuuma na Masteru. Tako se potpuno osloba\u0111amo sukoba replikacije. I sve nam dobro radi s izvje\u0161tajima.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/ee3c315168bdd3f392d2e8a1c5861004.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>A \u0161to se to doga\u0111a s na\u0161im Master poslu\u017eiteljem u to vrijeme? Na Master poslu\u017eitelju se doga\u0111a potpuna katastrofa. Trenutno promatramo grafove kada sam uklju\u010dio obje te postavke. I vidimo da je sesija na replici na neki na\u010din po\u010dela utjecati na situaciju na Master poslu\u017eitelju. Doista utje\u010de jer je obustavila automatski vakuum koji \u010disti mrtve redove. Veli\u010dina tablice ponovno je naglo porasla. Prosje\u010dno vrijeme izvr\u0161avanja upita kroz cijelu bazu podataka tako\u0111er se naglo pove\u0107alo. Automatski vakuumi su se malo napregnuli. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/980611dcce8b189dc50f422ffd3d2d72.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Specifi\u010dno za na\u0161u tablicu vidimo da je i a\u017euriranje podataka sko\u010dilo u nebesa. Potro\u0161nja procesorskih resursa tako\u0111er se zna\u010dajno pove\u0107ala. Ponovno pretra\u017eujemo veliko mno\u017estvo mrtvih beskorisnih redova. I vrijeme odgovora na ovu tablicu, broj transakcija opao je. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/a648fd313a5dccf45f0056dc13c54263.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kako \u0107e to izgledati ako ne znamo o \u010demu sam govorio do sada?<\/p>\n<p><\/p>\n<ul>\n<li>Zapo\u010dinjemo s pronala\u017eenjem problema. Ako smo se susretali s problemima u prvom dijelu, znamo da bi razlog mogla biti duga\u010dka transakcija i i\u0161li bismo na Master. Problem imamo na Masteru. Svi\u0111a se njemu. Zagrijava se, Load Average mu je blizu stotke. <\/li>\n<li>Zahtjevi su tamo usporeni, ali ne vidimo nikakve dugotrajne transakcije. I ne razumijemo u \u010demu je problem. Ne znamo gdje tra\u017eiti. <\/li>\n<li>Provjeravamo serversku opremu. Mo\u017eda nam je RAID propao. Mo\u017eda je memorijska traka pregorjela. \u0160to god mo\u017ee biti. No, ne, serveri su novi, sve radi odli\u010dno. <\/li>\n<li>Svi tr\u010de: administratori, programeri i direktor. Ni\u0161ta ne poma\u017ee. <\/li>\n<li>I u nekom trenutku sve iznenada po\u010dinje samo od sebe ispravljati. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/7d4f6417bc5cb3cec33679d843c6661d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Na replici nam je u to vrijeme zahtjev odra\u0111en i oti\u0161ao. Dobili smo izvje\u0161taj. Posao je jo\u0161 uvijek zadovoljan. Kao \u0161to vidimo, tablica nam je opet narasla i ne planira se smanjiti. Na grafikonu sa sesijama ostavio sam komadi\u0107 ove duge transakcije s replike, kako biste mogli procijeniti koliko dugo traje dok se situacija stabilizira. <\/p>\n<p><\/p>\n<p>Sesija je oti\u0161la. I tek nakon nekog vremena server dolazi vi\u0161e-manje u red. I prosje\u010dno vrijeme odgovora na zahtjeve na Master serveru dolazi u normu. Jer, kona\u010dno, auto-vakuum je dobio priliku da o\u010disti, ozna\u010di te mrtve retke. I on je po\u010deo raditi svoj posao. I koliko brzo radi, toliko brzo \u0107emo do\u0107i u red.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/547d195e08de1566da818150a47218eb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Na ispitnoj tablici, gdje a\u017euriramo stanje ra\u010duna, vidimo potpuno istu sliku. Prosje\u010dno vrijeme a\u017euriranja ra\u010duna tako\u0111er se postupno normalizira. Resursi koje procesor tro\u0161i tako\u0111er se smanjuju. I broj transakcija u sekundi se vra\u0107a u normu. No opet, ne u normu kakva je bila prije kvara. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/29372a5e9124690931485a7aea65befc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>U svakom slu\u010daju, dobijamo pad performansi kao u prvom slu\u010daju od jedan i pol do dva puta, a ponekad i vi\u0161e. <\/p>\n<p><\/p>\n<p>Izgleda da smo u\u010dinili sve ispravno. Rasporedili smo optere\u0107enje. Oprema ne miruje. Razumno smo raspodijelili zahtjeve, ali svejedno je ispalo lo\u0161e. <\/p>\n<p><\/p>\n<ul>\n<li>Ne uklju\u010dujte hot_standby_feedback? Da, ne preporu\u010duje se uklju\u010divanje bez posebnih razloga. Ova opcija izravno utje\u010de na glavnog poslu\u017eitelja i pauzira rad automatske vakuumske operacije. Ako ga uklju\u010dite na nekoj replici i zaboravite na to, mo\u017eete o\u0161tetiti glavnog i dobiti velike probleme s aplikacijom. <\/li>\n<li>Pove\u0107ati max_standby_streaming_delay? Da, to je to\u010dno za izvje\u0161taje. Ako imate tro\u010dasovni izvje\u0161taj i ne \u017eelite da se prekine zbog sukoba repliciranja, jednostavno pove\u0107ajte ka\u0161njenje. Dugi izvje\u0161taji nikada ne zahtijevaju podatke koji su do\u0161li u bazu upravo sada. Ako je tro\u010dasovni, to zna\u010di da ga pokre\u0107ete za neki stari period podataka. I za vas, da li imate tri sata ka\u0161njenja ili \u0161est, ne\u0107e igrati veliku ulogu, ali \u0107ete stabilno primati izvje\u0161taje bez problema s njihovim prekidom. <\/li>\n<li>Naravno, potrebno je kontrolirati duge sesije na replikama, posebno ako ste odlu\u010dili uklju\u010diti hot_standby_feedback na replici. Jer mo\u017ee se dogoditi bilo \u0161to. Dali ste tu replicu programeru da testira upite. Napisao je nevjerojatan upit. Pokrenuo je i oti\u0161ao piti kavu, a mi smo dobili zauzetog glavnog. Ili smo pustili neotu aplikaciju. Situacije su razne. Sesije na replikama potrebno je kontrolirati jednako pa\u017eljivo kao i na glavnom. <\/li>\n<li>I ako imate brze i duge upite na replikama, u tom slu\u010daju je bolje za raspodjelu optere\u0107enja razdvojiti ih. Ovo se odnosi na streaming_delay. Za brze, imajte jednu replikaciju s malim ka\u0161njenjem replikacije. Za duge izvje\u0161tajne upite imajte replikaciju koja mo\u017ee kasniti 6 sati, pa \u010dak i do jednog dana. To je sasvim normalna situacija. <\/li>\n<\/ul>\n<p><\/p>\n<p>Uklanjamo posljedice na isti na\u010din:<\/p>\n<p><\/p>\n<ul>\n<li>Nalazimo napuhane tablice.<\/li>\n<li>I komprimiramo ih najprikladnijim alatom koji nam odgovara. <\/li>\n<\/ul>\n<p><\/p>\n<p>Druga pri\u010da ovdje zavr\u0161ava. Idemo na tre\u0107u pri\u010du. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/c8784e0be27883640cb8f6919a1c25e0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tako\u0111er prili\u010dno uobi\u010dajena za nas, u kojoj radimo migraciju. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/a04b9cd88a0e7e8a3b960ef930eb2657.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<ul>\n<li>Svaki softverski proizvod raste. Promjenjuju se zahtjevi za njim. Uvijek \u017eelimo napredovati. I doga\u0111a se da je ponekad potrebno a\u017eurirati podatke u tablici, to\u010dno pokrenuti a\u017euriranje u okviru na\u0161e migracije za novu funkcionalnost koju uvodimo kao dio na\u0161eg razvoja. <\/li>\n<li>Stari format podataka nam ne odgovara. Pretpostavimo da se sada obra\u0107amo drugoj tablici, gdje imam operacije po tim ra\u010dunima. I, pretpostavimo, da su bile u rubaljima, a mi smo odlu\u010dili pove\u0107ati to\u010dnost i raditi u kopejkama. I za to trebamo napraviti a\u017euriranje: polje sa iznosom operacije pomno\u017eiti sa sto. <\/li>\n<li>U dana\u0161njem svijetu koristimo automatizirane alate za kontrolu verzija baza podataka. Pretpostavljam, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/\">Liquibase<\/a><\/noindex>. Upisujemo na\u0161u migraciju. Testiramo je na na\u0161oj testnoj bazi. Sve je u redu. A\u017euriranje prolazi. Blokira rad na neko vrijeme, ali tako dobivamo a\u017eurirane podatke. I mo\u017eemo pokrenuti novu funkcionalnost na tome. Sve je testirano, provjereno. Sve je potvr\u0111eno. <\/li>\n<li>Proveli smo planirane radove, izvr\u0161ili migraciju. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/9e046583f7b1723fc1eaf61a03900918.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Evo migracije s a\u017euriranjem predstavljene pred vama. Kako su to operacije po ra\u010dunima, tablica je imala 15 GB. I budu\u0107i da a\u017euriramo svaki redak, pove\u0107ali smo tablicu na dvostruko, jer smo prepisali svaki redak. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/06120c98ea43d0568045e71935c23592.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tijekom migracije nismo mogli raditi s ovom tablicom, jer su svi upiti prema njoj \u010dekali u redu i \u010dekali da se to a\u017euriranje zavr\u0161i. No, ovdje \u017eelim skrenuti va\u0161u pozornost na brojke koje se nalaze na vertikalnoj osi. Odnosno, imamo prosje\u010dno vrijeme upita prije migracije oko 5 milisekundi i optere\u0107enje na procesoru, broj blokovskih operacija \u010ditanja memorije diska je manji od 7,5. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/69a3ba4d1d0cec7d39284e09e9d3055b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Izvr\u0161ili smo migraciju i ponovo dobili probleme. <\/p>\n<p><\/p>\n<p>Migracija je pro\u0161la uspje\u0161no, ali:<\/p>\n<p><\/p>\n<ul>\n<li>Stara funkcionalnost postala je sporija. <\/li>\n<li>Tablica se ponovo pove\u0107ala u veli\u010dini. <\/li>\n<li>Optere\u0107enje na serveru ponovo je postalo ve\u0107e nego \u0161to je bilo. <\/li>\n<li>I, naravno, jo\u0161 uvijek se bavimo onom funkcionalno\u0161\u0107u koja je dobro radila, malo smo je pobolj\u0161ali. <\/li>\n<\/ul>\n<p><\/p>\n<p>I to je ponovo bloat koji nam opet kvari \u017eivot. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/becd7cce3a1c8821c81c96257f41202b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ovdje pokazujem da se tablica, kao i u prethodna dva slu\u010daja, ne planira vra\u0107ati na prethodne veli\u010dine. Prosje\u010dno optere\u0107enje na serveru izgleda razmjerno. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/4d703a60d43a3460bc3782d49865b690.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ako se obratimo tablici sa ra\u010dunima, vidjet \u0107emo da je prosje\u010dno vrijeme zahtjeva dvostruko poraslo u odnosu na tu tablicu. Optere\u0107enje na procesor i broj pretra\u017eivanih redova u memoriji sko\u010dili su iznad 7,5, a prije su bili ispod. Sko\u010dilo je dvostruko u slu\u010daju procesora, a u slu\u010daju blok operacija 1,5 puta, tj. do\u0161lo je do degradacije performansi servera. Kao rezultat toga - degradacija performansi na\u0161e aplikacije. Pri tome je broj poziva ostao otprilike na istoj razini. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/80772afa0643b29f5314a2482c9dfe0d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ovdje je va\u017eno razumjeti kako ispravno provoditi takve migracije. A one su neophodne. Ove migracije radimo prili\u010dno redovito.<\/p>\n<p><\/p>\n<ul>\n<li>Takve velike migracije se ne rade automatski. One uvijek moraju biti pod kontrolom. <\/li>\n<li>Potrebna je kontrola od strane iskusne osobe. Ako imate DBA u timu, neka to radi DBA. To je njegov posao. Ako nemate, neka to u\u010dini najiskusnija osoba koja zna raditi s bazama podataka. <\/li>\n<li>Nova shema baze podataka, \u010dak i ako a\u017euriramo samo jedan stupac, uvijek se priprema u fazama, tj. unaprijed prije nego \u0161to se nova verzija aplikacije izvr\u0161i:<\/li>\n<li>Dodaju se nova polja u koja \u0107emo zapisivati a\u017eurirane podatke. <\/li>\n<li>Prebacujemo podatke iz starog polja u novo polje u manjim dijelovima. Za\u0161to to radimo? Prvo, uvijek kontroliramo proces ovog prebacivanja. Znamo da smo prenijeli odre\u0111eni broj batch-eva i da nam jo\u0161 ostaje toliki. <\/li>\n<li>A druga pozitivna stvar je to da izme\u0111u svakog takvog batch-a zatvaramo transakciju, otvaramo novu i to omogu\u0107ava automatskom vakuumu da odradi svoj posao na tablici, ozna\u010davaju\u0107i mrtve redove za ponovnu upotrebu. <\/li>\n<li>Za redove koji \u0107e se pojaviti tijekom rada aplikacije (starija aplikacija jo\u0161 uvijek radi) dodajemo okida\u010d koji zapisuje nove vrijednosti u nova polja. U na\u0161em slu\u010daju - to je mno\u017eenje starog vrijednosti s sto. <\/li>\n<li>Ako smo potpuno uporni i \u017eelimo isto to polje, onda, nakon zavr\u0161etka svih migracija i prije implementacije nove verzije aplikacije, jednostavno preimenujemo polja. Stara u neko izmi\u0161ljeno ime, a nova polja preimenujemo u stara. <\/li>\n<li>Tek nakon toga pokre\u0107emo novu verziju aplikacije. <\/li>\n<\/ul>\n<p><\/p>\n<p>I pritom ne\u0107emo dobiti bloat i ne\u0107emo pogor\u0161ati performanse. <\/p>\n<p><\/p>\n<p>Ovdje se zavr\u0161ila tre\u0107a pri\u010da. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/2afab2906b5ccd30e4c8772248818057.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pg-utils\/blob\/master\/sql\/table_bloat.sql\">https:\/\/github.com\/dataegret\/pg-utils\/blob\/master\/sql\/table_bloat.sql<\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pg-utils\/blob\/master\/sql\/table_bloat_approx.sql\">https:\/\/github.com\/dataegret\/pg-utils\/blob\/master\/sql\/table_bloat_approx.sql<\/a><\/noindex><\/p>\n<p><\/p>\n<p>Sada \u0107u malo detaljnije objasniti alate koje sam spomenuo u prvoj pri\u010di. <\/p>\n<p><\/p>\n<p>Prije nego \u0161to po\u010dnete tra\u017eiti bloat, obavezno instalirajte pro\u0161irenje. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/pgstattuple.html\">pgstattuple<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Da vam ne bih smi\u0161ljao upite, ve\u0107 smo ih napisali u na\u0161oj praksi. Mo\u017eete ih koristiti. Ovdje su predstavljena dva upita. <\/p>\n<p><\/p>\n<ul>\n<li>Prvi traje dosta dugo, ali \u0107e vam pokazati to\u010dne vrijednosti bloat-a po tablici. <\/li>\n<li>Drugi radi br\u017ee i vrlo je u\u010dinkovit kada je potrebno brzo procijeniti \u2014 postoji li bloat ili ne po tablici. Tako\u0111er morate razumjeti da bloat u Postgres tablicama uvijek postoji. To je posebnost njegovog MVCC modela. <\/li>\n<li>I 20% bloat-a je normalno za tablice u ve\u0107ini slu\u010dajeva. Dakle, ne trebate se previ\u0161e brinuti i komprimirati ovu tablicu. <\/li>\n<\/ul>\n<p><\/p>\n<p>Kako identificirati tablice koje su nam se napuhale, razjasnili smo, pa \u010dak i kada su se napuhale beskorisnim podacima. <\/p>\n<p><\/p>\n<p>Sada o tome kako ispraviti bloat:<\/p>\n<p><\/p>\n<ul>\n<li>Ako imamo malu tablicu i dobre diskove, to jest, ako je tablica manja od jednog gigabajta, mogu\u0107e je koristiti VACUUM FULL. Uze\u0107e ekskluzivnu blokadu na tablici na nekoliko sekundi, ali \u0107e sve u\u010diniti brzo i efikasno. \u0160to radi VACUUM FULL? Uzimaje ekskluzivnu blokadu na tablicu i iz starih tablica prepisuje aktivne redove u novu tablicu. Na kraju zamijeni stare i nove. Stare datoteke bri\u0161e, nove postavlja umjesto starih. Ali tokom svog rada uzima ekskluzivnu blokadu tablice. To zna\u010di da s tom tablicom ne\u0107ete mo\u0107i raditi ni\u0161ta: ne mo\u017eete pisati, \u010ditati ili modificirati je. Tako\u0111er, VACUUM FULL zahtijeva dodatni prostor na disku za zapis podataka.<\/li>\n<li>Sljede\u0107i alat <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">pg_repack<\/a><\/noindex>. Po svom principu je vrlo sli\u010dan VACUUM FULL, jer tako\u0111er prepisuje podatke iz starih datoteka u nove i zamjenjuje ih u tablici. Ali ne uzima ekskluzivnu blokadu na tablici na samom po\u010detku svog rada, ve\u0107 samo u trenutku kada ve\u0107 ima pripremljene podatke za zamjenu datoteka. Zahtjevi za diskovnim resursima su sli\u010dni onima kod VACUUM FULL. Trebat \u0107e vam dodatni prostor na disku, a to ponekad mo\u017ee biti kriti\u010dno, ako imate tablice od jednog terabajta. Tako\u0111er je prili\u010dno zahtjevan prema procesoru, jer aktivno radi s unosom i izlazom. <\/li>\n<li>Tre\u0107a alatka je <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">pgcompacttable<\/a><\/noindex>. Pona\u0161a se \u0161tedljivije prema resursima jer radi na malo druga\u010dijim principima. Su\u0161tina pgcompacttable je u tome \u0161to a\u017euriranjem u tablici premje\u0161ta sve aktivne redove na po\u010detak tablice. Zatim pokre\u0107e vakuum na toj tablici, jer znamo da su na po\u010detku aktivni, a na kraju neaktivni redovi. A vakuum ve\u0107 sam odrezuje taj rep, tj. ne zahtijeva previ\u0161e dodatnog prostor. Tako\u0111er ga je jo\u0161 mogu\u0107e optimizirati prema resursima. <\/li>\n<\/ul>\n<p><\/p>\n<p>Sa alatima je sve. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uobi\u010dajene gre\u0161ke u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov\" src=\"\/wp-content\/uploads\/2020\/05\/4187915e54e54a0b85a342fe0280f78f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ako vam tema o bloat-u izgleda zanimljivo za dublje istra\u017eivanje, evo nekih korisnih linkova:<\/p>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.slideshare.net\/alexius2Mb\/where-is-the-space-postgres\">https:\/\/www.slideshare.net\/alexius2Mb\/where-is-the-space-postgres<\/a><\/noindex> \u2013 to je izlaganje mog kolege. Osnovna je to tema o tome gdje prostor nestaje u Postgresu tijekom njegova rada i \u017eivotnog ciklusa. Ima veliki i detaljan tehni\u010dki dio za administratore baza podataka o bloat-u. <\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pg-utils\">https:\/\/github.com\/dataegret\/pg-utils<\/a><\/noindex> \u2013 to je link na na\u0161 repozitorij, gdje \u010duvamo mno\u0161tvo korisnih skripti za provjeru stanja baze podataka. Tamo mo\u017eete prona\u0107i skripte za pronala\u017eenje bloat-a. <\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">Tre\u0107i<\/a><\/noindex> i <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">\u010detiri<\/a><\/noindex> linkovi na alate koji \u0107e vam pomo\u0107i da optimizirate tablice. <\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/blog.dataegret.com\/2Mb018\/03\/postgresql-bloatbusters.html\">http:\/\/blog.dataegret.com\/2Mb018\/03\/postgresql-bloatbusters.html<\/a><\/noindex> \u2013 to je post mog kolege. Tamo prou\u010dava bloat na razini bli\u017eoj administratorima, prili\u010dno ozbiljno i detaljno. <\/li>\n<\/ul>\n<p><\/p>\n<p>Poku\u0161ao sam ovdje vi\u0161e prikazati zastra\u0161uju\u0107u sliku za developere, jer su oni na\u0161i neposredni klijenti baza podataka i trebaju razumjeti do koje mjere i kakve akcije vode. Nadam se da mi je to uspjelo. Hvala na pa\u017enji!<\/p>\n<p><\/p>\n<p>Pitanja<\/p>\n<p><\/p>\n<p><em>Hvala za izlaganje! Govorili ste o tome kako mogu identificirati probleme. Kako ih mogu prevenirati? Imala sam situaciju kada su upiti visjeli ne samo zbog pozivanja nekih vanjskih servisa. Bili su to jednostavno neki divlji joins. Imali smo neke sitne ne\u0161kodljive upite koji su visjeli danima, a zatim su po\u010deli raditi neku glupost. Zna\u010di, jako sli\u010dno onome \u0161to opisujete. Kako to pratiti? Treba li sjediti i stalno gledati koji upit je visio? Kako to prevenirati?<\/em><\/p>\n<p><\/p>\n<p>U ovom slu\u010daju \u2013 to je zadatak za administratore va\u0161e tvrtke, ne nu\u017eno za DBA.<\/p>\n<p><\/p>\n<p><em>Ja sam administrator.<\/em><\/p>\n<p><\/p>\n<p>U PostgreSQL postoji prikaz nazvan pg_stat_activity, koji prikazuje visjele upite. Tamo mo\u017eete vidjeti koliko dugo su visjeli.<\/p>\n<p><\/p>\n<p><em>Treba li da svake 5 minuta provjeravam?<\/em><\/p>\n<p><\/p>\n<p>Postavite cron i provjerite. Ako imate dug zahtjev, pi\u0161ite email i to je to. Odnosno, ne morate to gledati vlastitim o\u010dima, to se mo\u017ee automatizirati. Do\u0107i \u0107e vam e-mail, vi reagirate na njega. A mo\u017eete i automatski ispaliti.<\/p>\n<p><\/p>\n<p><em>Postoje li o\u010diti razlozi za\u0161to se to doga\u0111a?<\/em><\/p>\n<p><\/p>\n<p>Neke sam naveo. Drugi su slo\u017eeniji primjeri. I tu bi razgovor mogao potrajati.<\/p>\n<p><\/p>\n<p><em>Hvala na prezentaciji! Htio sam pojasniti vezano uz alat pg_repack. Ako ne pravi ekskluzivnu blokadu, onda\u2026<\/em><\/p>\n<p><\/p>\n<p>Ona pravi ekskluzivnu blokadu. <\/p>\n<p><\/p>\n<p>\u2026 <em>onda potencijalno mogu izgubiti podatke. Moja aplikacija ne bi trebala ni\u0161ta zapisivati u to vrijeme?<\/em><\/p>\n<p><\/p>\n<p>Ne, ona mirno radi s tablicom, tj. pg_repack prvo premje\u0161ta sve aktivne redove koji postoje. Naravno, tamo se odvija neka vrsta zapisa u tablici. On jednostavno dodaje taj ostatak. <\/p>\n<p><\/p>\n<p><em>Odnosno, na kraju ipak to radi?<\/em><\/p>\n<p><\/p>\n<p>Na kraju uzima ekskluzivnu blokadu kako bi zamijenio ta mjesta izme\u0111u tih datoteka. <\/p>\n<p><\/p>\n<p><em>Ho\u0107e li to biti br\u017ee od VACUUM FULL?<\/em><\/p>\n<p><\/p>\n<p>VACUUM FULL, \u010dim po\u010dne, odmah uzima ekskluzivnu blokadu. I sve dok ne zavr\u0161i, ne pu\u0161ta je. A pg_repack uzima ekskluzivnu blokadu samo u trenutku zamjene datoteka. U tom trenutku ne mo\u017eete zapisivati, ali podaci se ne\u0107e izgubiti, sve \u0107e biti u redu. <\/p>\n<p><\/p>\n<p><em>Dobar dan! Govorili ste o radu automatskog vakuuma. Tamo je bio grafikon s crvenim, \u017eutim i zelenim \u0107elijama zapisa. Odnosno, \u017eute \u2013 on je ozna\u010dio kao obrisane. I kao posljedica mo\u017ee li se u njih zapisivati novo?<\/em><\/p>\n<p><\/p>\n<p>Da. Postgres ne bri\u0161e redove. Ima tu specifi\u010dnost. Ako smo a\u017eurirali red, stare ozna\u010dimo kao obrisane. Tada se postavlja ID transakcije koja je izmijenila taj red i zapisujemo novi red. I imamo sesije koje potencijalno mogu \u010ditati te redove. U nekom trenutku oni postaju sasvim stari. A su\u0161tina rada automatskog vakuuma je da prolazi kroz te redove i ozna\u010dava ih kao nepotrebne. I ondje se mogu prepisati podaci. <\/p>\n<p><\/p>\n<p><em>Razumijem. No pitanje nije ba\u0161 to. Nisam zavr\u0161io. Pretpostavimo da imamo tablicu. U njoj su polja promjenjive veli\u010dine. I ako poku\u0161am umetnuti ne\u0161to novo, tada to mo\u017eda ne\u0107e stati u staru \u0107eliju.<\/em> <\/p>\n<p><\/p>\n<p>Ne, u svakom slu\u010daju cijela linija se a\u017eurira. U Postgresu postoje dva modela pohrane podataka. Odre\u0111uje se prema vrsti podataka. Postoje podaci koji se pohranjuju izravno u tablicu, a tu su i tos-podaci. To su velike koli\u010dine podataka: tekst, json. Oni se pohranjuju u posebnim tablicama. I sa tim tablicama doga\u0111a se isto \u0161to i s bloat-om, tj. sve je isto. Samo su odvojeni. <\/p>\n<p><\/p>\n<p><em>Hvala na izlaganju! Koliko je prihvatljivo koristiti requests statement timeout za ograni\u010davanje trajanja upita?<\/em><\/p>\n<p><\/p>\n<p>Vrlo je prihvatljivo. Mi to koristimo svugdje. A budu\u0107i da nemamo vlastite usluge, pru\u017eamo udaljenu podr\u0161ku, te imamo prili\u010dno raznolike klijente. Svi su posve zadovoljni. Tj. imamo zadatke u cron-u koji provjeravaju. Jednostavno se s klijentom dogovara trajanje sesija, ispod kojeg ne \u201cubijamo\u201d. To mo\u017ee biti minuta, to mo\u017ee biti 10 minuta. Ovisi o optere\u0107enju baze i njezinoj svrsi. Ali svi koristimo pg_stat_activity.<\/p>\n<p><\/p>\n<p><em>Hvala na izlaganju! Poku\u0161avam prilagoditi va\u0161e izlaganje svojim aplikacijama. I \u010dinilo mi se da svugdje zapo\u010dinjemo transakciju, svugdje je izri\u010dito zavr\u0161avamo. Ako do\u0111e do bilo kakvog exception-a, rollback se ionako odvija. I onda sam se zamislio. Naime, transakcija se mo\u017ee pokrenuti neizravno. To je mo\u017eda sugestija za djevojku. Ako jednostavno a\u017euriram zapis, transakcija \u0107e se pokrenuti u PostgreSQL-u i zavr\u0161it \u0107e tek kada do\u0111e do prekida veze?<\/em><\/p>\n<p><\/p>\n<p>Ako sada govorite o razini aplikacije, to ovisi o onome \u0161to koristite, o tom ORM-u koji se koristi. Tu je jako puno postavki. Ako imate uklju\u010deno auto commit on, tada se transakcija pokre\u0107e i odmah zatvara.<\/p>\n<p><\/p>\n<p><em>Tj. zatvara se odmah nakon a\u017euriranja?<\/em><\/p>\n<p><\/p>\n<p>To ovisi o postavkama. Jednu postavku sam spomenuo. To je auto commit on. To je prili\u010dno rasprostranjeno. Ako je uklju\u010deno, transakcija se otvorila-zatvorila. Ako izri\u010dito ne ka\u017eete 'start transaction' i 'end transaction', nego jednostavno pokrenete upit u sesiji. <\/p>\n<p><\/p>\n<p><em>Dobar dan! Hvala na izlaganju! Pretpostavimo da imamo bazu koja se \u0161iri i na serveru nestaje prostora. Postoje li neki alati kako bi se to rije\u0161ilo?<\/em> <\/p>\n<p><\/p>\n<p>Prostor na serveru treba pratiti. <\/p>\n<p><\/p>\n<p><em>Na primjer, DBA je oti\u0161ao na \u010daj, bio je na odmoru itd.<\/em><\/p>\n<p><\/p>\n<p>Kada se stvara datote\u010dni sustav, minim\u00e1ln\u011b se stvara neka rezervirana povr\u0161ina gdje se ne pohranjuju podaci. <\/p>\n<p><\/p>\n<p><em>A ako potpuno na nuli?<\/em><\/p>\n<p><\/p>\n<p>Tamo se to naziva rezervirani prostor, odnosno, mo\u017ee se osloboditi, a ovisno o tome koliko je velik stvoren, dobivate slobodan prostor. Po defaultu ne znam koliko tamo ima. A u drugom slu\u010daju \u2013 dostaviti diskove da imate prostor za izvo\u0111enje postupka obnove. Mo\u017eete obrisati neku tablicu koja vam sigurno nije potrebna. <\/p>\n<p><\/p>\n<p><em>Nema drugih alata?<\/em><\/p>\n<p><\/p>\n<p>To je uvijek ru\u010dni rad. I na licu mjesta se utvr\u0111uje \u0161ta je bolje u\u010diniti, jer postoje kriti\u010dni podaci, postoje nekriti\u010dni. I za svaku bazu i aplikaciju koja s njom radi, to ovisi o poslovanju. Uvijek se odlu\u010duje na licu mjesta. <\/p>\n<p><\/p>\n<p><em>Hvala na prezentaciji! Imam dva pitanja. Prvo, demonstrirali ste slajdove na kojima je prikazano da, u slu\u010daju zaklju\u010denih transakcija, raste i volumen tabli\u010dnog prostora i veli\u010dina indeksa. A zatim u prezentaciji je bilo mnogo alata koji pakiraju tablicu. A \u0161ta je sa indeksom?<\/em><\/p>\n<p><\/p>\n<p>Oni tako\u0111er pakiraju indekse. <\/p>\n<p><\/p>\n<p><em>Ali vakuum ne zahva\u0107a indeks?<\/em><\/p>\n<p><\/p>\n<p>Neki rade s indeksom. Na primjer, pg_rapack, pgcompacttable. Vakuum ponovno stvara indekse, zahva\u0107a ih. Su\u0161tina VACUUM FULL je da sve prepisuje, t.j. radi sa svima. <\/p>\n<p><\/p>\n<p><em>I drugo pitanje. Nisam razumio za\u0161to izvje\u0161taji na replikama tako jako ovise o samoj replikaciji. Mislio sam da su izvje\u0161taji \u2013 to je \u010ditanje, a replikacija \u2013 to je pisanje.<\/em> <\/p>\n<p><\/p>\n<p>U \u010demu se javlja konflikt replikacije? Imamo Master odakle se odvijaju procesi. Ovdje se odvija autovakuum. Autovakuum zapravo radi \u0161ta? Uklanja neke stare retke. Ako u ovom trenutku na replici ide upit koji \u010dita te stare retke, a na Masteru se dogodila situacija gdje je autovakuum ozna\u010dio te retke kao mogu\u0107ne za prepisivanje, onda ih prepisujemo. I dolazi nam paket podataka kada trebamo prepisati one retke koji su potrebni upitu na replici, proces replikacije \u0107e \u010dekati onaj timeout koji ste postavili. A potom \u0107e PostgreSQL odlu\u010diti \u0161to je va\u017enije za njega. A replikacija je njemu va\u017enija od upita i on \u0107e obustaviti upit da izvr\u0161i te promjene na replici. <\/p>\n<p><\/p>\n<p><em>Andrej, imam pitanje. Ove divne grafike koje ste prikazali tijekom prezentacije, jesu li to rezultati rada neke va\u0161e alatke? \u010cime su graficirane grafike?<\/em><\/p>\n<p><\/p>\n<p>To je usluga <noindex><a rel=\"nofollow\" href=\"https:\/\/okmeter.io\/\">Okmeter<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><em>Je li to komercijalni proizvod?<\/em><\/p>\n<p><\/p>\n<p>Da. To je komercijalni proizvod.<\/p>\n<p>Izvor: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/501040\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 2016 \u0433\u043e\u0434\u0430 \u0410\u043d\u0434\u0440\u0435\u044f \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432\u0430 &quot;\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql&quot; \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u044f \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0418 \u0432\u043e\u0437\u044c\u043c\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043e\u0448\u0438\u0431\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 Postgresql. \u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u044d\u0442\u043e \u043d\u0430\u0447\u0430\u043b\u043e \u043a\u043e\u043d\u0446\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":81090,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-81089","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 2016 \u0433\u043e\u0434\u0430 \u0410\u043d\u0434\u0440\u0435\u044f \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432\u0430 &quot;\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql&quot; \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u044f \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"hr_HR\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql. \u0410\u043d\u0434\u0440\u0435\u0439 \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 2016 \u0433\u043e\u0434\u0430 \u0410\u043d\u0434\u0440\u0435\u044f \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432\u0430 &quot;\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql&quot; \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u044f \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-05-10T23:42:24+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-05-10T23:42:24+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Uobi\u010dajene gre\u0161ke u aplikacijama koje vode do bloat-a u PostgreSQL-u. Andrej Salnikov | ProHoster","description":"Predla\u017eem da se upoznate s transkriptom izlaganja Andreja Salnikova s po\u010detka 2016. godine pod nazivom \"Uobi\u010dajene gre\u0161ke u aplikacijama koje vode do bloat-a u PostgreSQL-u\". U ovom izlaganju \u0107u razraditi glavne.","canonical_url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"hr_HR","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql. \u0410\u043d\u0434\u0440\u0435\u0439 \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432 | ProHoster","og:description":"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 2016 \u0433\u043e\u0434\u0430 \u0410\u043d\u0434\u0440\u0435\u044f \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432\u0430 &quot;\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql&quot; \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u044f \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435.","og:url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-05-10T23:42:24+00:00","article:modified_time":"2020-05-10T23:42:24+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"81089","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 16:05:22","updated":"2022-09-27 16:01:50","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/81089","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/comments?post=81089"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/81089\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media\/81090"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media?parent=81089"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/categories?post=81089"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/tags?post=81089"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}