Postgres: bloat, pg_repack og frestað takmarkanir

Postgres: bloat, pg_repack og frestað takmarkanir

Áhrif uppþembu á töflur og vísitölur eru víða þekkt og eru ekki aðeins til staðar í Postgres. Það eru til leiðir til að takast á við það út úr kassanum, eins og VACUUM FULL eða CLUSTER, en þau læsa borðum meðan á notkun stendur og því er ekki alltaf hægt að nota þau.

Greinin mun innihalda smá kenningu um hvernig uppþemba á sér stað, hvernig þú getur barist við það, um frestað þvingun og vandamálin sem þær hafa í för með sér við notkun pg_repack viðbótarinnar.

Þessi grein er skrifuð út frá ræðu mína á PgConf.Russia 2020.

Af hverju kemur uppþemba?

Postgres er byggt á fjölútgáfu líkani (MVCC). Kjarni þess er að hver röð í töflunni getur haft nokkrar útgáfur, á meðan viðskipti sjá ekki fleiri en eina af þessum útgáfum, en ekki endilega sömu. Þetta gerir nokkrum færslum kleift að virka samtímis og hafa nánast engin áhrif á hvort annað.

Augljóslega þarf að geyma allar þessar útgáfur. Postgres vinnur með minni síðu fyrir síðu og síða er lágmarksmagn gagna sem hægt er að lesa af diski eða skrifa. Við skulum skoða lítið dæmi til að skilja hvernig þetta gerist.

Segjum að við höfum töflu sem við höfum bætt nokkrum færslum við. Ný gögn hafa birst á fyrstu síðu skráarinnar þar sem taflan er geymd. Þetta eru lifandi útgáfur af línum sem eru tiltækar fyrir aðrar færslur eftir commit (til einföldunar munum við gera ráð fyrir að einangrunarstigið sé Read Committed).

Postgres: bloat, pg_repack og frestað takmarkanir

Við uppfærðum síðan eina af færslunum og merktum þar með gömlu útgáfuna sem ekki lengur viðeigandi.

Postgres: bloat, pg_repack og frestað takmarkanir

Skref fyrir skref, með því að uppfæra og eyða línuútgáfum, enduðum við með síðu þar sem um það bil helmingur gagnanna er „sorp“. Þessi gögn eru ekki sýnileg neinum viðskiptum.

Postgres: bloat, pg_repack og frestað takmarkanir

Postgres hefur vélbúnað VACUUM, sem hreinsar út úreltar útgáfur og gerir pláss fyrir ný gögn. En ef það er ekki stillt nógu hart eða er upptekið við að vinna í öðrum töflum, þá verða „sorpgögn“ eftir og við verðum að nota viðbótarsíður fyrir ný gögn.

Svo í okkar dæmi, einhvern tíma mun taflan samanstanda af fjórum síðum, en aðeins helmingur hennar mun innihalda lifandi gögn. Þar af leiðandi munum við lesa mun fleiri gögn en nauðsynlegt er þegar við opnum töfluna.

Postgres: bloat, pg_repack og frestað takmarkanir

Jafnvel þó VACUUM eyði nú öllum óviðkomandi raðaútgáfum mun ástandið ekki batna verulega. Við munum hafa laust pláss á síðum eða jafnvel heilum síðum fyrir nýjar línur, en við munum samt lesa fleiri gögn en nauðsynlegt er.
Við the vegur, ef alveg auð síða (síðari í dæminu okkar) væri í lok skráarinnar, þá myndi VACUUM geta klippt hana. En núna er hún á miðjunni þannig að ekkert er hægt að gera við hana.

Postgres: bloat, pg_repack og frestað takmarkanir

Þegar fjöldi slíkra tómra eða mjög fárra síðna verður mikill, sem kallast uppblásinn, fer það að hafa áhrif á árangur.

Allt sem lýst er hér að ofan er vélfræði þess að uppþemba sé í töflum. Í vísitölum gerist þetta á svipaðan hátt.

Er ég með uppþembu?

Það eru nokkrar leiðir til að ákvarða hvort þú sért með uppþembu. Hugmyndin að því fyrsta er að nota innri Postgres tölfræði, sem inniheldur áætlaðar upplýsingar um fjölda raða í töflum, fjölda „lifandi“ raða osfrv. Þú getur fundið mörg afbrigði af tilbúnum skriftum á Netinu. Við lögðum til grundvallar handrit frá PostgreSQL sérfræðingum, sem geta metið uppblásturstöflur ásamt ristuðu brauði og uppblástursvísitölum. Reynsla okkar er sú að villa hennar er 10-20%.

Önnur leið er að nota viðbótina pgstattuple, sem gerir þér kleift að líta inn á síðurnar og fá bæði áætlað og nákvæmt uppblástursgildi. En í öðru tilvikinu verður þú að skanna alla töfluna.

Við teljum lítið uppþembagildi, allt að 20%, ásættanlegt. Það má líta á það sem hliðstæðu við fillfactor fyrir borðum и vísitölur. Við 50% og yfir geta frammistöðuvandamál hafist.

Leiðir til að berjast gegn uppþembu

Postgres hefur nokkrar leiðir til að takast á við uppþembu úr kassanum, en þær henta ekki alltaf öllum.

Stilltu AUTOVACUUM þannig að uppþemba komi ekki fram. Eða nánar tiltekið, til að halda því á því stigi sem þér er ásættanlegt. Þetta virðist vera ráð „fyrirliða“, en í raun er þetta ekki alltaf auðvelt að ná. Til dæmis, þú ert með virka þróun með reglulegum breytingum á gagnaskemanu eða einhvers konar gagnaflutningur á sér stað. Fyrir vikið getur hleðslusniðið þitt breyst oft og er venjulega mismunandi eftir töflum. Þetta þýðir að þú þarft stöðugt að vinna aðeins á undan og stilla AUTOVACUUM að breyttu sniði hvers borðs. En þetta er augljóslega ekki auðvelt að gera.

Önnur algeng ástæða fyrir því að AUTOVACUUM getur ekki fylgst með töflum er vegna þess að það eru langvarandi viðskipti sem koma í veg fyrir að það hreinsi upp gögnin sem eru tiltæk fyrir þessi viðskipti. Tilmælin hér eru líka augljós - losaðu þig við „hangandi“ viðskipti og lágmarkaðu tíma virkra viðskipta. En ef álagið á forritið þitt er blendingur af OLAP og OLTP, þá geturðu samtímis fengið margar tíðar uppfærslur og stuttar fyrirspurnir, svo og langtímaaðgerðir - til dæmis að búa til skýrslu. Í slíkum aðstæðum er þess virði að hugsa um að dreifa álaginu á mismunandi undirstöður, sem gerir kleift að fínstilla hvern þeirra.

Annað dæmi - jafnvel þótt sniðið sé einsleitt, en gagnagrunnurinn er undir mjög miklu álagi, þá gæti jafnvel árásargjarnasta AUTOVACUUM ekki ráðið við, og uppblásinn mun eiga sér stað. Skala (lóðrétt eða lárétt) er eina lausnin.

Hvað á að gera í aðstæðum þar sem þú hefur sett upp AUTOVACUUM, en uppblásinn heldur áfram að vaxa.

Team TÚMSÚG FULLT endurbyggir innihald töflur og vísitölur og skilur aðeins eftir viðeigandi gögn í þeim. Til að útrýma uppþembu virkar það fullkomlega, en meðan á framkvæmd þess stendur er einkalás á borðinu tekin (AccessExclusiveLock), sem leyfir ekki að framkvæma fyrirspurnir á þessu borði, jafnvel velur. Ef þú hefur efni á að stöðva þjónustu þína eða hluta hennar í nokkurn tíma (frá tugum mínútna til nokkurra klukkustunda eftir stærð gagnagrunnsins og vélbúnaðarins), þá er þessi valkostur bestur. Því miður höfum við ekki tíma til að keyra VACUUM FULL meðan á áætlaðu viðhaldi stendur, þannig að þessi aðferð hentar okkur ekki.

Team CLOSTER Endurbyggir innihald taflna á sama hátt og VACUUM FULL, en gerir þér kleift að tilgreina vísitölu eftir því sem gögnin verða líkamlega raðað á disk (en í framtíðinni er röðin ekki tryggð fyrir nýjar línur). Við ákveðnar aðstæður er þetta góð hagræðing fyrir fjölda fyrirspurna - með lestri margra skráa eftir vísitölu. Ókosturinn við skipunina er sá sami og við VACUUM FULL - hún læsir borðinu meðan á notkun stendur.

Team ENDURFARIÐ svipað og fyrri tveir, en endurbyggir ákveðna vísitölu eða allar vísitölur töflunnar. Lásar eru örlítið veikari: ShareLock á borðinu (kemur í veg fyrir breytingar, en leyfir vali) og AccessExclusiveLock á vísitölunni sem verið er að endurbyggja (lokar fyrir fyrirspurnum sem nota þessa vísitölu). Hins vegar, í 12. útgáfu af Postgres birtist breytu SAMKVÆMT, sem gerir þér kleift að endurbyggja vísitöluna án þess að hindra samhliða viðbót, breytingu eða eyðingu skráa.

Í fyrri útgáfum af Postgres geturðu náð svipaðri niðurstöðu og REINDEX Samtímis með því að nota BÚÐU TIL VÍSITALA SAMTÍMI. Það gerir þér kleift að búa til vísitölu án strangrar læsingar (ShareUpdateExclusiveLock, sem truflar ekki samhliða fyrirspurnir), skipta síðan út gömlu vísitölunni fyrir nýja og eyða gömlu vísitölunni. Þetta gerir þér kleift að útrýma vísitöluuppþembu án þess að trufla umsókn þína. Það er mikilvægt að hafa í huga að þegar vísitölur eru endurbyggðar verður aukið álag á undirkerfi disksins.

Svona, ef fyrir vísitölur eru leiðir til að útrýma uppþembu „á flugu,“ þá eru engar fyrir töflur. Þetta er þar sem ýmsar ytri viðbætur koma við sögu: pg_repack (áður pg_reorg), pgcompact, pgcompacttable og aðrir. Í þessari grein mun ég ekki bera þær saman og mun aðeins tala um pg_repack, sem við notum sjálf eftir nokkrar breytingar.

Hvernig pg_repack virkar

Postgres: bloat, pg_repack og frestað takmarkanir
Segjum að við séum með algjörlega venjulegt borð - með vísitölum, takmörkunum og því miður með uppþembu. Fyrsta skref pg_repack er að búa til annálatöflu til að geyma gögn um allar breytingar á meðan hún er í gangi. Kveikjan mun endurtaka þessar breytingar fyrir hverja innsetningu, uppfærslu og eyðingu. Þá er búið til tafla, svipað og upprunalega að uppbyggingu, en án vísitölu og takmarkana, til að hægja ekki á innsetningu gagna.

Næst flytur pg_repack gögnin úr gömlu töflunni yfir í nýju töfluna, síar sjálfkrafa út allar óviðkomandi línur og býr síðan til vísitölur fyrir nýju töfluna. Við framkvæmd allra þessara aðgerða safnast breytingar upp í logtöflunni.

Næsta skref er að flytja breytingarnar yfir á nýju töfluna. Flutningurinn er framkvæmdur í nokkrum endurtekningum og þegar færri en 20 færslur eru eftir í logtöflunni fær pg_repack sterkan lás, flytur nýjustu gögnin og skiptir gömlu töflunni út fyrir þá nýju í Postgres kerfistöflunum. Þetta er eini og mjög stutti tíminn sem þú munt ekki geta unnið með borðið. Eftir þetta er gömlu töflunni og töflunni með annálum eytt og pláss losað í skráarkerfinu. Ferlið er lokið.

Allt lítur vel út í orði, en hvað gerist í reynd? Við prófuðum pg_repack án álags og undir álagi og athuguðum virkni þess ef ótímabært stöðvaði (með öðrum orðum, með því að nota Ctrl+C). Öll prófin voru jákvæð.

Við fórum í matvörubúðina - og þá fór allt ekki eins og við bjuggumst við.

Fyrsta pönnukakan á útsölu

Í fyrsta þyrpingunni fengum við villu um brot á einstakri þvingun:

$ ./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.

Þessi takmörkun var með sjálfvirkt myndað nafn index_16508 - það var búið til af pg_repack. Byggt á eiginleikum sem eru í samsetningu þess, ákváðum við „okkar“ þvingun sem samsvarar henni. Vandamálið reyndist vera að þetta er ekki alveg venjuleg takmörkun, heldur frestað (frestað þvingun), þ.e. Staðfesting þess er framkvæmd seinna en sql skipunin, sem leiðir til óvæntra afleiðinga.

Frestað skorður: hvers vegna þeirra er þörf og hvernig þær virka

Smá kenning um frestað höft.
Við skulum íhuga einfalt dæmi: við höfum töfluuppvísunarbók yfir bíla með tveimur eiginleikum - nafn og röð bílsins í skránni.
Postgres: bloat, pg_repack og frestað takmarkanir

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



Segjum að við þurftum að skipta um fyrsta og annan bílinn. Einfalda lausnin er að uppfæra fyrsta gildið í annað og annað í það fyrsta:

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

En þegar við keyrum þennan kóða, gerum við ráð fyrir þvingunarbroti vegna þess að röð gildanna í töflunni er einstök:

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

Hvernig get ég gert það öðruvísi? Valkostur eitt: Bættu við viðbótarvirðisuppbót við pöntun sem tryggt er að sé ekki til í töflunni, til dæmis „-1“. Í forritun er þetta kallað "að skiptast á gildum tveggja breyta í gegnum þriðju." Eini gallinn við þessa aðferð er viðbótaruppfærslan.

Valkostur tvö: Endurhanna töfluna til að nota fljótandi gagnategund fyrir pöntunargildið í stað heiltalna. Síðan, þegar gildið er uppfært úr 1, til dæmis, í 2.5, mun fyrsta færslan sjálfkrafa „standa“ á milli annarrar og þriðju. Þessi lausn virkar, en það eru tvær takmarkanir. Í fyrsta lagi mun það ekki virka fyrir þig ef gildið er notað einhvers staðar í viðmótinu. Í öðru lagi, allt eftir nákvæmni gagnategundarinnar, muntu hafa takmarkaðan fjölda mögulegra innskots áður en þú endurreiknar gildi allra skráa.

Valkostur þrjú: Gerðu þvingunina frestað þannig að hún sé aðeins hakuð við skuldbindinguna:

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

Þar sem rökfræði upphaflegrar beiðni okkar tryggir að öll gildi séu einstök við skuldbindinguna, mun það takast.

Dæmið sem fjallað er um hér að ofan er auðvitað mjög tilbúið, en það sýnir hugmyndina. Í forritinu okkar notum við frestað skorður til að innleiða rökfræði sem er ábyrg fyrir að leysa átök þegar notendur vinna samtímis með sameiginlegum græjuhlutum á borðinu. Notkun slíkra takmarkana gerir okkur kleift að gera forritskóðann aðeins einfaldari.

Almennt séð, allt eftir tegund þvingunar, hefur Postgres þrjú nákvæmnistig til að athuga þau: röð, viðskipti og tjáningarstig.
Postgres: bloat, pg_repack og frestað takmarkanir
Heimild: begriffs

CHECK og NOT NULL eru alltaf merkt við á línustigi; fyrir aðrar takmarkanir, eins og sjá má af töflunni, eru mismunandi valkostir. Þú getur lesið meira hér.

Til að draga saman í stuttu máli þá veita frestar skorður í ýmsum aðstæðum læsilegri kóða og færri skipanir. Hins vegar verður þú að borga fyrir þetta með því að flækja villuleitarferlið, þar sem augnablikið sem villan kemur upp og augnablikið sem þú kemst að því eru aðskilin í tíma. Annað hugsanlegt vandamál er að tímaáætlunarmaðurinn getur ekki alltaf smíðað ákjósanlega áætlun ef beiðnin felur í sér frestað þvingun.

Endurbætur á pg_repack

Við höfum farið yfir hvað frestað takmarkanir eru, en hvernig tengjast þær vandamálinu okkar? Við skulum muna villuna sem við fengum áðan:

$ ./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.

Það gerist þegar gögn eru afrituð úr annálatöflu yfir í nýja töflu. Þetta lítur undarlega út því... gögnin í annálatöflunni eru skuldbundin ásamt gögnunum í upprunatöflunni. Ef þeir fullnægja takmörkunum upprunalegu töflunnar, hvernig geta þeir brotið gegn sömu takmörkunum í þeirri nýju?

Eins og það kemur í ljós liggur rót vandans í fyrra skrefi pg_repack, sem skapar aðeins vísitölur, en ekki takmarkanir: gamla taflan hafði einstaka þvingun og sú nýja bjó til einstaka vísitölu í staðinn.

Postgres: bloat, pg_repack og frestað takmarkanir

Það er mikilvægt að hafa í huga hér að ef þvingunin er eðlileg og ekki frestað, þá er einstaka vísitalan sem búin er til í staðinn jafngild þessari þvingun, vegna þess að Einstakar takmarkanir í Postgres eru útfærðar með því að búa til einstaka vísitölu. En ef um frestað þvingun er að ræða er hegðunin ekki sú sama, því ekki er hægt að fresta vísitölunni og er alltaf hakað við á þeim tíma sem sql skipunin er keyrð.

Þannig liggur kjarni vandans í „töfinni“ á athuguninni: í upprunalegu töflunni kemur það fram við skuldbindinguna og í nýju töflunni á þeim tíma sem sql skipunin er keyrð. Þetta þýðir að við þurfum að ganga úr skugga um að athuganir séu gerðar eins í báðum tilfellum: annað hvort alltaf seinkað eða alltaf strax.

Svo hvaða hugmyndir höfðum við?

Búðu til vísitölu svipað og frestað

Fyrsta hugmyndin er að framkvæma báðar athuganir strax. Þetta getur valdið nokkrum fölskum jákvæðum takmörkunum, en ef þær eru fáar ætti þetta ekki að hafa áhrif á vinnu notenda, þar sem slík átök eru eðlilegt ástand fyrir þá. Þeir eiga sér stað til dæmis þegar tveir notendur byrja að breyta sömu græjunni á sama tíma og viðskiptavinur seinni notandans hefur ekki tíma til að fá upplýsingar um að fyrsti notandinn hafi lokað á græjuna til að breyta henni. Í slíkum aðstæðum neitar þjónninn öðrum notandanum og viðskiptavinur hans afturkallar breytingarnar og lokar á búnaðinn. Nokkru síðar, þegar fyrsti notandinn lýkur breytingunni, mun sá síðari fá upplýsingar um að búnaðurinn sé ekki lengur læstur og hann geti endurtekið aðgerð sína.

Postgres: bloat, pg_repack og frestað takmarkanir

Til að tryggja að ávísanir séu alltaf í ófrestaðri stillingu, bjuggum við til nýja vísitölu sem líkist upprunalegu frestuðu takmörkunum:

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

Í prófunarumhverfinu fengum við aðeins nokkrar villur sem búist var við. Árangur! Við keyrðum pg_repack aftur í framleiðslu og fengum 5 villur á fyrsta þyrpingunni á klukkutíma vinnu. Þetta er ásættanleg niðurstaða. Hins vegar, þegar á seinni klasanum fjölgaði villunum verulega og við urðum að hætta pg_repack.

Hvers vegna gerðist það? Líkurnar á að villa komi upp fer eftir því hversu margir notendur eru að vinna með sömu búnaðinn á sama tíma. Svo virðist sem á því augnabliki hafi verið mun færri samkeppnisbreytingar með gögnin sem geymd eru á fyrsta klasanum en á hinum, þ.e. við vorum bara "heppin".

Hugmyndin gekk ekki upp. Á þeim tímapunkti sáum við tvær aðrar lausnir: endurskrifa umsóknarkóðann okkar til að losna við frestaðar takmarkanir, eða „kenna“ pg_repack að vinna með þær. Við völdum þann seinni.

Skiptu út vísitölum í nýju töflunni með frestaðum takmörkunum frá upprunalegu töflunni

Tilgangur endurskoðunarinnar var augljós - ef upphaflega taflan hefur frestað þvingun, þá þarftu að búa til slíka þvingun fyrir þá nýju en ekki vísitölu.

Til að prófa breytingarnar okkar skrifuðum við einfalt próf:

  • tafla með frestað þvingun og einni skrá;
  • setja inn gögn í lykkju sem stangast á við núverandi skrá;
  • gerðu uppfærslu - gögnin stangast ekki lengur á;
  • framið breytingarnar.

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;

Upprunalega útgáfan af pg_repack hrundi alltaf við fyrstu innsetningu, breytta útgáfan virkaði án villna. Frábært.

Við förum í framleiðslu og fáum aftur villu í sama áfanga við að afrita gögn úr annálatöflunni yfir í nýja:

$ ./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.

Klassískar aðstæður: allt virkar í prófunarumhverfi, en ekki í framleiðslu?!

APPLY_COUNT og mótum tveggja lota

Við byrjuðum að greina kóðann bókstaflega línu fyrir línu og uppgötvuðum mikilvægan punkt: gögn eru flutt úr skráningartöflunni yfir í nýjan í lotum, APPLY_COUNT fastinn gaf til kynna stærð lotunnar:

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

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

Vandamálið er að gögnin frá upphaflegu færslunni, þar sem nokkrar aðgerðir gætu hugsanlega brotið í bága við takmörkunina, þegar þau eru flutt, geta endað á mótum tveggja lota - helmingur skipana verður framinn í fyrstu lotu og hinn helmingurinn í seinni. Og hér, allt eftir heppni þinni: ef liðin brjóta ekki neitt í fyrstu lotunni, þá er allt í lagi, en ef þau gera það, kemur upp villa.

APPLY_COUNT er jafnt og 1000 færslur, sem útskýrir hvers vegna prófanirnar okkar heppnuðust - þær náðu ekki yfir „lotumót“. Við notuðum tvær skipanir - setja inn og uppfæra, þannig að nákvæmlega 500 færslur af tveimur skipunum voru alltaf settar í lotu og við lentum ekki í neinum vandræðum. Eftir að hafa bætt við seinni uppfærslunni hætti breytingin okkar að virka:

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;

Svo, næsta verkefni er að ganga úr skugga um að gögn úr upprunalegu töflunni, sem var breytt í einni færslu, endi í nýju töflunni líka innan einnar færslu.

Neitun frá skömmtun

Og aftur höfðum við tvær lausnir. Í fyrsta lagi: við skulum hætta algjörlega að skipta í lotur og flytja gögn í einni færslu. Kosturinn við þessa lausn var einfaldleiki hennar - nauðsynlegar kóðabreytingar voru í lágmarki (við the vegur, í eldri útgáfum virkaði pg_reorg nákvæmlega svona). En það er vandamál - við erum að búa til langvarandi viðskipti og þetta, eins og áður sagði, er ógn við tilkomu nýrrar uppblásturs.

Önnur lausnin er flóknari, en líklega réttari: búðu til dálk í logtöflunni með auðkenni færslunnar sem bætti gögnum við töfluna. Síðan, þegar við afritum gögn, getum við flokkað þau eftir þessum eiginleikum og tryggt að tengdar breytingar séu fluttar saman. Lotan verður mynduð úr nokkrum færslum (eða einni stórri) og stærð hennar er breytileg eftir því hversu miklum gögnum var breytt í þessum viðskiptum. Það er mikilvægt að hafa í huga að þar sem gögn úr mismunandi færslum fara inn í annálatöfluna í handahófskenndri röð verður ekki lengur hægt að lesa þau í röð eins og áður. seqscan fyrir hverja beiðni með síun eftir tx_id er of dýrt, vísitölu er þörf, en það mun einnig hægja á aðferðinni vegna kostnaðar við að uppfæra hana. Almennt, eins og alltaf, þarftu að fórna einhverju.

Þannig að við ákváðum að byrja á fyrsta valkostinum, þar sem hann er einfaldari. Í fyrsta lagi var nauðsynlegt að skilja hvort löng viðskipti væru raunverulegt vandamál. Þar sem aðalflutningur gagna frá gömlu töflunni yfir í þá nýju á sér einnig stað í einni langri færslu breyttist spurningin í „hversu mikið munum við auka þessi viðskipti? Lengd fyrstu viðskipta fer aðallega eftir stærð borðsins. Lengd nýrrar fer eftir því hversu margar breytingar safnast fyrir í töflunni við gagnaflutninginn, þ.e. á styrkleika álagsins. Pg_repack keyrslan átti sér stað á tíma með lágmarks þjónustuálagi og magn breytinga var óhóflega lítið miðað við upprunalega stærð töflunnar. Við ákváðum að við gætum vanrækt tíma nýrrar viðskipta (til samanburðar er það að meðaltali 1 klukkustund og 2-3 mínútur).

Tilraunirnar voru jákvæðar. Ræsa í framleiðslu líka. Til glöggvunar er hér mynd með stærð eins af gagnagrunnum eftir að hafa verið keyrt:

Postgres: bloat, pg_repack og frestað takmarkanir

Þar sem við vorum alveg sáttir við þessa lausn reyndum við ekki að innleiða þá seinni, en við erum að íhuga möguleikann á að ræða það við framlengingarframleiðendurna. Núverandi endurskoðun okkar, því miður, er ekki enn tilbúin til útgáfu, þar sem við leystum vandamálið aðeins með einstökum frestuðum takmörkunum, og fyrir fullan plástur er nauðsynlegt að veita stuðning fyrir aðrar tegundir. Við vonumst til að geta gert þetta í framtíðinni.

Kannski hefurðu spurningu, hvers vegna tókum við þátt í þessari sögu með breytingunni á pg_repack, og notuðum til dæmis ekki hliðstæður þess? Á einhverjum tímapunkti hugsuðum við líka um þetta, en jákvæð reynsla af því að nota það fyrr, á borðum án frestaðra takmarkana, hvatti okkur til að reyna að skilja kjarna vandamálsins og laga það. Að auki þarf tíma til að framkvæma prófanir að nota aðrar lausnir, svo við ákváðum að fyrst myndum við reyna að laga vandamálið í því, og ef við áttuðum okkur á því að við gætum ekki gert þetta á hæfilegum tíma, þá myndum við byrja að skoða hliðstæður .

Niðurstöður

Það sem við getum mælt með byggt á eigin reynslu:

  1. Fylgstu með uppþembu þinni. Byggt á vöktunargögnum geturðu skilið hversu vel sjálfvirkt tómarúm er stillt.
  2. Stilltu AUTOVACUUM til að halda uppþembu á viðunandi stigi.
  3. Ef uppþemba er enn að vaxa og þú getur ekki sigrast á því með því að nota út-af-the-box verkfæri, ekki vera hræddur við að nota ytri viðbætur. Aðalatriðið er að prófa allt vel.
  4. Ekki vera hræddur við að breyta ytri lausnum til að henta þínum þörfum - stundum getur þetta verið skilvirkara og jafnvel auðveldara en að breyta eigin kóða.

Heimild: www.habr.com

Bæta við athugasemd