Postgres: bloat, pg_repack i odgođena ograničenja

Postgres: bloat, pg_repack i odgođena ograničenja

Efekat nadimanja na tabele i indekse je opšte poznat i prisutan je ne samo u Postgresu. Postoje načini da se s tim pozabavite izvan kutije, poput VACUUM FULL ili CLUSTER, ali oni zaključavaju stolove tokom rada i stoga se ne mogu uvijek koristiti.

Članak će sadržavati malo teorije o tome kako nastaje nadimanje, kako se možete boriti protiv njega, o odgođenim ograničenjima i problemima koje oni donose u korištenju ekstenzije pg_repack.

Ovaj članak je napisan na osnovu moj govor na PgConf.Russia 2020.

Zašto se javlja nadimanje?

Postgres je zasnovan na modelu sa više verzija (MVCC). Njegova suština je da svaki red u tabeli može imati nekoliko verzija, dok transakcije ne vide više od jedne od ovih verzija, ali ne nužno istu. Ovo omogućava da nekoliko transakcija rade istovremeno i da praktično nemaju uticaj jedna na drugu.

Očigledno, sve ove verzije moraju biti pohranjene. Postgres radi sa memorijom stranicu po stranicu, a stranica je minimalna količina podataka koja se može pročitati sa diska ili napisati. Pogledajmo mali primjer da shvatimo kako se to događa.

Recimo da imamo tabelu u koju smo dodali nekoliko zapisa. Novi podaci su se pojavili na prvoj stranici datoteke u kojoj je pohranjena tabela. Ovo su žive verzije redova koji su dostupni drugim transakcijama nakon urezivanja (radi jednostavnosti, pretpostavićemo da je nivo izolacije Read Committed).

Postgres: bloat, pg_repack i odgođena ograničenja

Zatim smo ažurirali jedan od unosa, čime smo staru verziju označili kao nerelevantnu.

Postgres: bloat, pg_repack i odgođena ograničenja

Korak po korak, ažuriranjem i brisanjem verzija redaka, na kraju smo dobili stranicu na kojoj je otprilike polovina podataka “smeće”. Ovi podaci nisu vidljivi nijednoj transakciji.

Postgres: bloat, pg_repack i odgođena ograničenja

Postgres ima mehanizam VACUUM, koji čisti zastarjele verzije i stvara prostor za nove podatke. Ali ako nije dovoljno agresivno konfigurisan ili je zauzet radom u drugim tabelama, onda ostaju „podaci smeća“ i moramo koristiti dodatne stranice za nove podatke.

Dakle, u našem primjeru, u nekom trenutku tabela će se sastojati od četiri stranice, ali samo polovina će sadržavati podatke uživo. Kao rezultat toga, kada pristupamo tabeli, pročitaćemo mnogo više podataka nego što je potrebno.

Postgres: bloat, pg_repack i odgođena ograničenja

Čak i ako VACUUM sada izbriše sve nebitne verzije reda, situacija se neće dramatično poboljšati. Imat ćemo slobodan prostor na stranicama ili čak cijelim stranicama za nove redove, ali ćemo i dalje čitati više podataka nego što je potrebno.
Usput, ako je potpuno prazna stranica (druga u našem primjeru) na kraju datoteke, tada bi VACUUM mogao da je skrati. Ali sada je ona u sredini, tako da se ništa ne može učiniti s njom.

Postgres: bloat, pg_repack i odgođena ograničenja

Kada broj takvih praznih ili vrlo rijetkih stranica postane velik, što se naziva napuhanost, to počinje utjecati na performanse.

Sve gore opisano je mehanika pojave nadimanja u tabelama. U indeksima se to dešava na skoro isti način.

Imam li nadutost?

Postoji nekoliko načina da utvrdite imate li nadimanje. Ideja prvog je korištenje interne Postgres statistike, koja sadrži približne informacije o broju redova u tabelama, broju "živih" redova itd. Na internetu možete pronaći mnoge varijacije gotovih skripti. Uzeli smo za osnovu skripta od PostgreSQL Experts, koji može procijeniti naduvane tabele zajedno sa indeksima tost i bloat btree. Prema našem iskustvu, njegova greška je 10-20%.

Drugi način je korištenje ekstenzije pgstattuple, što vam omogućava da pogledate unutar stranica i dobijete i procijenjenu i tačnu vrijednost napuhanosti. Ali u drugom slučaju, morat ćete skenirati cijelu tablicu.

Smatramo da je prihvatljiva mala vrijednost nadimanja, do 20%. Može se smatrati analogom faktora popunjavanja za stolovi и indeksi. Na 50% i više, mogu početi problemi s performansama.

Načini borbe protiv nadimanja

Postgres ima nekoliko načina za rješavanje nadimanja izvan kutije, ali oni nisu uvijek prikladni za svakoga.

Konfigurirajte AUTOVAKUUM tako da ne dođe do nadimanja. Ili preciznije, da ga održite na nivou koji vam je prihvatljiv. Ovo izgleda kao "kapetanov" savjet, ali u stvarnosti to nije uvijek lako postići. Na primjer, imate aktivan razvoj s redovnim promjenama šeme podataka ili se odvija neka vrsta migracije podataka. Kao rezultat, vaš profil učitavanja može se često mijenjati i obično će se razlikovati od tabele do tabele. To znači da morate stalno raditi malo unaprijed i prilagoditi AUTOVAKUUM promjenjivom profilu svakog stola. Ali očigledno to nije lako učiniti.

Još jedan uobičajeni razlog zašto AUTOVACUUM ne može pratiti tablice je taj što postoje dugotrajne transakcije koje ga sprečavaju da očisti podatke koji su dostupni tim transakcijama. Preporuka je i ovdje očigledna - riješite se "visećih" transakcija i minimizirajte vrijeme aktivnih transakcija. Ali ako je opterećenje vaše aplikacije hibrid OLAP-a i OLTP-a, tada možete istovremeno imati mnogo čestih ažuriranja i kratkih upita, kao i dugoročne operacije - na primjer, pravljenje izvještaja. U takvoj situaciji vrijedi razmisliti o raspodjeli opterećenja na različite baze, što će omogućiti finije podešavanje svake od njih.

Još jedan primjer - čak i ako je profil homogen, ali je baza podataka pod vrlo velikim opterećenjem, onda se čak ni najagresivniji AUTOVAKUUM možda neće nositi i doći će do nadimanja. Skaliranje (vertikalno ili horizontalno) je jedino rješenje.

Šta učiniti u situaciji kada ste postavili AUTOVAKUUM, ali nadutost nastavlja da raste.

tim VACUUM FULL ponovo gradi sadržaj tabela i indeksa i ostavlja samo relevantne podatke u njima. Da bi se eliminisao naduvavanje, radi savršeno, ali tokom njegovog izvršavanja se hvata ekskluzivna brava na tabeli (AccessExclusiveLock), koja neće dozvoliti izvršavanje upita na ovoj tabeli, čak ni selektuje. Ako možete priuštiti da zaustavite svoju uslugu ili njen dio na neko vrijeme (od desetina minuta do nekoliko sati ovisno o veličini baze podataka i vašem hardveru), onda je ova opcija najbolja. Nažalost, nemamo vremena da pokrenemo VACUUM FULL tokom planiranog održavanja, tako da nam ova metoda nije prikladna.

tim CLASTERI Ponovo gradi sadržaj tabela na isti način kao VACUUM FULL, ali vam omogućava da navedete indeks prema kojem će podaci biti fizički poređani na disku (ali u budućnosti redosled nije zagarantovan za nove redove). U određenim situacijama, ovo je dobra optimizacija za brojne upite - sa čitanjem više zapisa po indeksu. Nedostatak komande je isti kao kod VACUUM FULL - zaključava sto tokom rada.

tim REINDEX slično kao prethodna dva, ali ponovo gradi određeni indeks ili sve indekse tabele. Zaključavanja su nešto slabija: ShareLock na tabeli (sprečava modifikacije, ali dozvoljava odabir) i AccessExclusiveLock na indeksu koji se ponovo gradi (blokira upite koji koriste ovaj indeks). Međutim, u 12. verziji Postgresa pojavio se parametar U isto vrijeme, što vam omogućava da ponovo izgradite indeks bez blokiranja istovremenog dodavanja, modifikacije ili brisanja zapisa.

U ranijim verzijama Postgresa možete postići rezultat sličan REINDEX CONCURRENTLY koristeći KREIRAJTE INDEKS ISPOREDNO. Omogućava vam da kreirate indeks bez strogog zaključavanja (ShareUpdateExclusiveLock, koji ne ometa paralelne upite), zatim zamijenite stari indeks novim i izbrišete stari indeks. Ovo vam omogućava da eliminišete naduvavanje indeksa bez ometanja vaše aplikacije. Važno je uzeti u obzir da će prilikom ponovne izgradnje indeksa doći do dodatnog opterećenja na podsistemu diska.

Dakle, ako za indekse postoje načini da se eliminiše nadimanje „u hodu“, onda ih nema za tabele. Ovdje se pojavljuju različiti vanjski ekstenzije: pg_repack (ranije pg_reorg), pgcompact, pgcompacttable i drugi. U ovom članku ih neću uspoređivati ​​i govorit ću samo o pg_repack-u koji, nakon nekih modifikacija, i sami koristimo.

Kako pg_repack radi

Postgres: bloat, pg_repack i odgođena ograničenja
Recimo da imamo sasvim običnu tabelu - sa indeksima, ograničenjima i, nažalost, sa naduvavanjem. Prvi korak pg_repack-a je kreiranje tabele dnevnika za pohranjivanje podataka o svim promjenama dok je pokrenut. Okidač će replicirati ove promjene za svako umetanje, ažuriranje i brisanje. Zatim se kreira tabela, po strukturi slična originalnoj, ali bez indeksa i ograničenja, kako se ne bi usporavao proces ubacivanja podataka.

Zatim, pg_repack prenosi podatke iz stare tablice u novu tablicu, automatski filtrirajući sve irelevantne redove, a zatim kreira indekse za novu tablicu. Tokom izvođenja svih ovih operacija, promjene se akumuliraju u tablici dnevnika.

Sljedeći korak je prijenos promjena u novu tabelu. Migracija se izvodi u nekoliko iteracija, a kada je u tablici dnevnika ostalo manje od 20 unosa, pg_repack preuzima snažno zaključavanje, migrira najnovije podatke i zamjenjuje staru tablicu novom u tablicama Postgres sistema. Ovo je jedino i vrlo kratko vrijeme kada nećete moći raditi sa stolom. Nakon toga, stara tabela i tabela sa evidencijama se brišu i oslobađa se prostor u sistemu datoteka. Proces je završen.

Sve izgleda odlično u teoriji, ali šta se dešava u praksi? Testirali smo pg_repack bez opterećenja i pod opterećenjem, te provjerili njegov rad u slučaju prijevremenog zaustavljanja (drugim riječima, pomoću Ctrl+C). Svi testovi su bili pozitivni.

Otišli smo u prodavnicu hrane - i onda sve nije išlo kako smo očekivali.

Prva palačinka u prodaji

Na prvom klasteru dobili smo grešku o kršenju jedinstvenog ograničenja:

$ ./pg_repack -t tablename -o id
INFO: repacking table "tablename"
ERROR: query failed: 
    ERROR: duplicate key value violates unique constraint "index_16508"
DETAIL:  Key (id, index)=(100500, 42) already exists.

Ovo ograničenje imalo je automatski generirano ime index_16508 - kreirao ga je pg_repack. Na osnovu atributa uključenih u njegov sastav, odredili smo „naše“ ograničenje koje mu odgovara. Ispostavilo se da je problem u tome što ovo nije sasvim obično ograničenje, već odloženo (odloženo ograničenje), tj. njegova verifikacija se vrši kasnije od sql naredbe, što dovodi do neočekivanih posljedica.

Odložena ograničenja: zašto su potrebna i kako funkcionišu

Malo teorije o odgođenim ograničenjima.
Razmotrimo jednostavan primjer: imamo tablicu-referencu automobila s dva atributa - imenom i redoslijedom automobila u imeniku.
Postgres: bloat, pg_repack i odgođena ograničenja

create table cars
(
  name text constraint pk_cars primary key,
  ord integer not null constraint uk_cars unique
);



Recimo da smo trebali zamijeniti prvi i drugi automobil. Jednostavno rješenje je ažuriranje prve vrijednosti na drugu, a drugu na prvu:

begin;
  update cars set ord = 2 where name = 'audi';
  update cars set ord = 1 where name = 'bmw';
commit;

Ali kada pokrenemo ovaj kod, očekujemo kršenje ograničenja jer je redoslijed vrijednosti u tabeli jedinstven:

[23305] ERROR: duplicate key value violates unique constraint “uk_cars”
Detail: Key (ord)=(2) already exists.

Kako to mogu učiniti drugačije? Prva opcija: dodajte dodatnu vrijednost zamjene narudžbi za koju je zajamčeno da ne postoji u tabeli, na primjer “-1”. U programiranju se to naziva "razmjena vrijednosti dvije varijable kroz treću". Jedini nedostatak ove metode je dodatno ažuriranje.

Druga opcija: Redizajnirajte tablicu tako da koristite tip podataka s pomičnim zarezom za vrijednost narudžbe umjesto cijelih brojeva. Zatim, kada ažurirate vrijednost sa 1, na primjer, na 2.5, prvi unos će automatski "stajati" između drugog i trećeg. Ovo rješenje funkcionira, ali postoje dva ograničenja. Prvo, neće raditi za vas ako se vrijednost koristi negdje u interfejsu. Drugo, ovisno o preciznosti tipa podataka, imat ćete ograničen broj mogućih umetanja prije ponovnog izračunavanja vrijednosti svih zapisa.

Opcija tri: učinite ograničenje odgođenim tako da se provjerava samo u vrijeme urezivanja:

create table cars
(
  name text constraint pk_cars primary key,
  ord integer not null constraint uk_cars unique deferrable initially deferred
);

Budući da logika našeg početnog zahtjeva osigurava da su sve vrijednosti jedinstvene u trenutku urezivanja, to će uspjeti.

Gornji primjer je, naravno, vrlo sintetički, ali otkriva ideju. U našoj aplikaciji koristimo odgođena ograničenja za implementaciju logike koja je odgovorna za rješavanje sukoba kada korisnici istovremeno rade sa zajedničkim widget objektima na ploči. Korištenje takvih ograničenja nam omogućava da učinimo kod aplikacije malo jednostavnijim.

Generalno, u zavisnosti od tipa ograničenja, Postgres ima tri nivoa granularnosti za njihovu proveru: nivo reda, transakcije i nivo izraza.
Postgres: bloat, pg_repack i odgođena ograničenja
izvor: begriffs

CHECK i NOT NULL se uvijek provjeravaju na nivou reda; za ostala ograničenja, kao što se može vidjeti iz tabele, postoje različite opcije. Možete pročitati više ovdje.

Ukratko da rezimiramo, odgođena ograničenja u brojnim situacijama pružaju čitljiviji kod i manje naredbi. Međutim, to morate platiti komplikacijom procesa otklanjanja grešaka, jer su trenutak kada se greška pojavi i trenutak kada saznate za nju vremenski razdvojeni. Drugi mogući problem je taj što planer možda neće uvijek moći konstruirati optimalan plan ako zahtjev uključuje odgođeno ograničenje.

Poboljšanje pg_repack-a

Pokrili smo šta su odložena ograničenja, ali kako se ona odnose na naš problem? Prisjetimo se greške koju smo ranije dobili:

$ ./pg_repack -t tablename -o id
INFO: repacking table "tablename"
ERROR: query failed: 
    ERROR: duplicate key value violates unique constraint "index_16508"
DETAIL:  Key (id, index)=(100500, 42) already exists.

Događa se kada se podaci kopiraju iz tablice dnevnika u novu tablicu. Ovo izgleda čudno jer... podaci u tablici dnevnika se urezuju zajedno s podacima u izvornoj tablici. Ako zadovoljavaju ograničenja originalne tablice, kako mogu prekršiti ista ograničenja u novoj?

Kako se ispostavilo, korijen problema leži u prethodnom koraku pg_repack, koji kreira samo indekse, ali ne i ograničenja: stara tablica je imala jedinstveno ograničenje, a nova je umjesto toga kreirala jedinstveni indeks.

Postgres: bloat, pg_repack i odgođena ograničenja

Ovdje je važno napomenuti da ako je ograničenje normalno i nije odgođeno, tada je jedinstveni indeks kreiran umjesto njega ekvivalentan ovom ograničenju, jer Jedinstvena ograničenja u Postgresu se implementiraju kreiranjem jedinstvenog indeksa. Ali u slučaju odgođenog ograničenja, ponašanje nije isto, jer se indeks ne može odgoditi i uvijek se provjerava u vrijeme izvršavanja sql naredbe.

Dakle, suština problema leži u “kašnjenju” provjere: u originalnoj tablici to se javlja u trenutku urezivanja, au novoj tablici u trenutku izvršavanja sql naredbe. To znači da se moramo pobrinuti da se provjere izvode na isti način u oba slučaja: uvijek odgođeno ili uvijek odmah.

Pa kakve smo ideje imali?

Kreirajte indeks sličan odloženom

Prva ideja je izvršiti obje provjere u trenutnom načinu rada. Ovo može stvoriti nekoliko lažno pozitivnih ograničenja, ali ako ih je malo, to ne bi trebalo utjecati na rad korisnika, jer su takvi sukobi za njih normalna situacija. Do njih dolazi, na primjer, kada dva korisnika počnu uređivati ​​isti widget u isto vrijeme, a klijent drugog korisnika nema vremena da primi informaciju da je widget već blokiran za uređivanje od strane prvog korisnika. U takvoj situaciji server odbija drugog korisnika, a njegov klijent vraća promjene i blokira widget. Malo kasnije, kada prvi korisnik završi uređivanje, drugi će dobiti informaciju da widget više nije blokiran i da će moći ponoviti svoju radnju.

Postgres: bloat, pg_repack i odgođena ograničenja

Kako bismo osigurali da su provjere uvijek u ne-odloženom načinu, kreirali smo novi indeks sličan izvornom odloženom ograničenju:

CREATE UNIQUE INDEX CONCURRENTLY uk_tablename__immediate ON tablename (id, index);
-- run pg_repack
DROP INDEX CONCURRENTLY uk_tablename__immediate;

U test okruženju smo dobili samo nekoliko očekivanih grešaka. Uspjeh! Ponovo smo pokrenuli pg_repack u produkciji i dobili 5 grešaka na prvom klasteru za sat vremena rada. Ovo je prihvatljiv rezultat. Međutim, već na drugom klasteru broj grešaka se značajno povećao i morali smo zaustaviti pg_repack.

Zašto se to dogodilo? Vjerojatnost pojave greške ovisi o tome koliko korisnika u isto vrijeme radi s istim widgetima. Očigledno je u tom trenutku bilo mnogo manje konkurentskih promjena s podacima pohranjenim na prvom klasteru nego na ostalima, tj. samo smo imali "sreću".

Ideja nije uspjela. U tom trenutku, vidjeli smo još dva rješenja: prepisati naš kod aplikacije kako bi se oslobodili odgođenih ograničenja ili „naučili“ pg_repack da radi s njima. Izabrali smo drugu.

Zamijenite indekse u novoj tablici s odgođenim ograničenjima iz originalne tablice

Svrha revizije je bila očigledna - ako originalna tabela ima odgođeno ograničenje, onda za novu morate kreirati takvo ograničenje, a ne indeks.

Da bismo testirali naše promjene, napisali smo jednostavan test:

  • tabela sa odgođenim ograničenjem i jednim zapisom;
  • ubaciti podatke u petlju koja je u sukobu sa postojećim zapisom;
  • izvršite ažuriranje – podaci više nisu u sukobu;
  • izvršite promjene.

create table test_table
(
  id serial,
  val int,
  constraint uk_test_table__val unique (val) deferrable initially deferred 
);

INSERT INTO test_table (val) VALUES (0);
FOR i IN 1..10000 LOOP
  BEGIN
    INSERT INTO test_table VALUES (0) RETURNING id INTO v_id;
    UPDATE test_table set val = i where id = v_id;
    COMMIT;
  END;
END LOOP;

Originalna verzija pg_repack-a je uvijek padala pri prvom umetanju, modificirana verzija je radila bez grešaka. Odlično.

Idemo u proizvodnju i opet dobijamo grešku u istoj fazi kopiranja podataka iz tabele dnevnika u novu:

$ ./pg_repack -t tablename -o id
INFO: repacking table "tablename"
ERROR: query failed: 
    ERROR: duplicate key value violates unique constraint "index_16508"
DETAIL:  Key (id, index)=(100500, 42) already exists.

Klasična situacija: sve radi u testnim okruženjima, ali ne i u produkciji?!

APPLY_COUNT i spoj dvije serije

Počeli smo analizirati kod doslovno red po red i otkrili važnu točku: podaci se prenose iz tablice dnevnika u novu u serijama, konstanta APPLY_COUNT je označavala veličinu serije:

for (;;)
{
num = apply_log(connection, table, APPLY_COUNT);

if (num > MIN_TUPLES_BEFORE_SWITCH)
     continue;  /* there might be still some tuples, repeat. */
...
}

Problem je u tome što podaci iz originalne transakcije, u kojoj bi nekoliko operacija potencijalno moglo narušiti ograničenje, kada se prenesu, mogu završiti na spoju dva paketa – polovina naredbi će biti izvršena u prvom paketu, a druga polovina u drugom. I ovdje, ovisno o vašoj sreći: ako timovi ne prekrše ništa u prvoj seriji, onda je sve u redu, ali ako to učine, dolazi do greške.

APPLY_COUNT je jednako 1000 zapisa, što objašnjava zašto su naši testovi bili uspješni - nisu pokrili slučaj „batch junction“. Koristili smo dvije komande - insert i update, tako da je tačno 500 transakcija dvije komande uvijek stavljeno u paketu i nismo imali nikakvih problema. Nakon dodavanja drugog ažuriranja, naše uređivanje je prestalo raditi:

FOR i IN 1..10000 LOOP
  BEGIN
    INSERT INTO test_table VALUES (1) RETURNING id INTO v_id;
    UPDATE test_table set val = i where id = v_id;
    UPDATE test_table set val = i where id = v_id; -- one more update
    COMMIT;
  END;
END LOOP;

Dakle, sljedeći zadatak je osigurati da podaci iz originalne tablice, koja je promijenjena u jednoj transakciji, završe u novoj tablici također unutar jedne transakcije.

Odbijanje mešanja

I opet smo imali dva rješenja. Prvo: hajde da potpuno napustimo particionisanje na grupe i prenesite podatke u jednoj transakciji. Prednost ovog rješenja bila je njegova jednostavnost - potrebne promjene koda su bile minimalne (usput rečeno, u starijim verzijama pg_reorg je radio upravo tako). Ali postoji problem - mi stvaramo dugotrajnu transakciju, a to je, kao što je ranije rečeno, prijetnja za pojavu novog nadimanja.

Drugo rješenje je složenije, ali vjerovatno ispravnije: kreirajte kolonu u tablici dnevnika s identifikatorom transakcije koja je dodala podatke u tablicu. Zatim, kada kopiramo podatke, možemo ih grupirati prema ovom atributu i osigurati da se povezane promjene prenesu zajedno. Grupa će biti formirana od nekoliko transakcija (ili jedne velike) i njena veličina će varirati u zavisnosti od toga koliko je podataka promenjeno u tim transakcijama. Važno je napomenuti da pošto podaci iz različitih transakcija ulaze u tabelu evidencije nasumičnim redosledom, više ih neće biti moguće čitati sekvencijalno, kao što je to bilo ranije. seqscan za svaki zahtjev sa filtriranjem po tx_id je preskup, potreban je indeks, ali će također usporiti metodu zbog prevelikih troškova ažuriranja. Generalno, kao i uvijek, treba nešto žrtvovati.

Dakle, odlučili smo da počnemo s prvom opcijom, jer je jednostavnija. Prvo je bilo potrebno razumjeti da li bi duga transakcija predstavljala pravi problem. Budući da se glavni prijenos podataka iz stare tablice u novu također odvija u jednoj dugoj transakciji, pitanje se transformiralo u "za koliko ćemo povećati ovu transakciju?" Trajanje prve transakcije zavisi uglavnom od veličine tabele. Trajanje novog zavisi od toga koliko se promena nakupi u tabeli tokom prenosa podataka, tj. na intenzitet opterećenja. Pokretanje pg_repack-a dogodilo se u vrijeme minimalnog opterećenja usluge, a obim promjena je bio neproporcionalno mali u odnosu na originalnu veličinu tablice. Odlučili smo da možemo zanemariti vrijeme nove transakcije (poređenja radi, u prosjeku je 1 sat i 2-3 minute).

Eksperimenti su bili pozitivni. Pokrenuti i proizvodnju. Radi jasnoće, evo slike s veličinom jedne od baza podataka nakon pokretanja:

Postgres: bloat, pg_repack i odgođena ograničenja

Budući da smo u potpunosti zadovoljni ovim rješenjem, nismo pokušavali implementirati drugo, ali razmatramo mogućnost da o tome razgovaramo sa programerima ekstenzija. Naša trenutna revizija, nažalost, još nije spremna za objavljivanje, jer smo problem riješili samo jedinstvenim odgođenim ograničenjima, a za punopravni zakrpu potrebno je osigurati podršku za druge vrste. Nadamo se da ćemo to moći učiniti u budućnosti.

Možda imate pitanje zašto smo se uopće uključili u ovu priču s modifikacijom pg_repacka, a nismo, na primjer, koristili njegove analoge? U nekom trenutku smo i mi razmišljali o tome, ali pozitivno iskustvo ranije upotrebe, na stolovima bez odgođenih ograničenja, motivisalo nas je da pokušamo razumjeti suštinu problema i popraviti ga. Osim toga, korištenje drugih rješenja također zahtijeva vrijeme za provođenje testova, pa smo odlučili da prvo pokušamo riješiti problem u njemu, a ako bismo shvatili da to ne možemo učiniti u razumnom roku, onda bismo krenuli u traženje analoga .

nalazi

Šta možemo preporučiti na osnovu sopstvenog iskustva:

  1. Pratite svoju nadutost. Na osnovu podataka praćenja, možete razumjeti koliko je dobro konfiguriran autovakuum.
  2. Podesite AUTOVAKUUM kako biste održali nadimanje na prihvatljivom nivou.
  3. Ako nadutost i dalje raste i ne možete je savladati korištenjem gotovih alata, nemojte se bojati koristiti vanjske ekstenzije. Glavna stvar je da sve dobro testirate.
  4. Nemojte se bojati modificirati vanjska rješenja kako bi odgovarala vašim potrebama – ponekad to može biti učinkovitije, pa čak i lakše od promjene vlastitog koda.

izvor: www.habr.com

Dodajte komentar