Postgres: bloat, pg_repack agus srianta iarchurtha

Postgres: bloat, pg_repack agus srianta iarchurtha

Tá eolas forleathan ar éifeacht bloat ar tháblaí agus ar innéacsanna agus tá sé i láthair ní hamháin i Postgres. Tá bealaí ann chun déileáil leis as an mbosca, cosúil le FOLAMH IOMLÁN nó CLUSTER, ach glasann siad táblaí le linn oibriú agus mar sin ní féidir iad a úsáid i gcónaí.

Beidh beagán teoiric san alt faoi conas a tharlaíonn bloat, conas is féidir leat é a chomhrac, faoi shrianta iarchurtha agus na fadhbanna a thugann siad le húsáid an síneadh pg_repack.

Tá an t-alt seo scríofa bunaithe ar mo chuid cainte ag PgConf.Russia 2020.

Cén fáth a dtarlaíonn bloat?

Tá Postgres bunaithe ar mhúnla illeagan (MVCC). Is é a bunúsach gur féidir go mbeadh roinnt leaganacha ag gach sraith sa tábla, cé nach bhfeiceann idirbhearta níos mó ná ceann amháin de na leaganacha seo, ach ní gá gurb ionann iad. Ligeann sé seo do roinnt idirbheart oibriú go comhuaineach agus is beag tionchar a bhíonn acu ar a chéile.

Ar ndóigh, is gá na leaganacha seo go léir a stóráil. Oibríonn Postgres le cuimhne leathanach ar leathanach agus is é leathanach an t-íosmhéid sonraí is féidir a léamh ó dhiosca nó ó scríobh. Breathnaímid ar shampla beag chun tuiscint a fháil ar conas a tharlaíonn sé seo.

Ligean le rá go bhfuil tábla againn a bhfuil roinnt taifead curtha leis againn. Tá sonraí nua le feiceáil ar an gcéad leathanach den chomhad ina bhfuil an tábla stóráilte. Is leaganacha beo iad seo de shraitheanna atá ar fáil d’idirbhearta eile tar éis gealltanas (ar mhaithe le simplíocht, glacfaimid leis gurb é Read Committed an leibhéal leithlisithe).

Postgres: bloat, pg_repack agus srianta iarchurtha

Ansin nuashonraíomar ceann de na hiontrálacha, rud a mharcáil an seanleagan mar nach mbaineann le hábhar a thuilleadh.

Postgres: bloat, pg_repack agus srianta iarchurtha

Céim ar chéim, ag nuashonrú agus ag scriosadh leaganacha sraithe, chríochnaigh muid leathanach ina bhfuil thart ar leath de na sonraí mar “truflais”. Níl na sonraí seo le feiceáil ag aon idirbheart.

Postgres: bloat, pg_repack agus srianta iarchurtha

Tá meicníocht ag Postgres VACUUM, a ghlanann leaganacha atá imithe i léig agus a dhéanann spás do shonraí nua. Ach mura bhfuil sé cumraithe sách ionsaitheach nó má tá sé gnóthach ag obair i dtáblaí eile, fanann “sonraí truflais”, agus ní mór dúinn leathanaigh bhreise a úsáid le haghaidh sonraí nua.

Mar sin inár sampla, ag am éigin ama beidh an tábla comhdhéanta de cheithre leathanach, ach ní bheidh ach leath de na sonraí beo. Mar thoradh air sin, agus muid ag teacht ar an tábla, léifimid i bhfad níos mó sonraí ná mar is gá.

Postgres: bloat, pg_repack agus srianta iarchurtha

Fiú má scriosann folúntas gach leagan as a chéile nach mbaineann le hábhar, ní thiocfaidh feabhas mór ar an scéal. Beidh spás saor in aisce againn i leathanaigh nó fiú leathanaigh iomlána le haghaidh sraitheanna nua, ach beidh níos mó sonraí fós á léamh againn ná mar is gá.
Dála an scéil, dá mbeadh leathanach go hiomlán bán (an dara ceann inár sampla) ag deireadh an chomhaid, ansin bheadh ​​VACUUM in ann é a bhearradh. Ach anois tá sí sa lár, mar sin ní féidir aon rud a dhéanamh léi.

Postgres: bloat, pg_repack agus srianta iarchurtha

Nuair a éiríonn líon na leathanach folamh nó an-ghann den sórt sin mór, ar a dtugtar bloat, tosaíonn sé ag cur isteach ar fheidhmíocht.

Is éard atá i ngach rud a thuairiscítear thuas ná meicníocht an tharla bloat i dtáblaí. In innéacsanna tarlaíonn sé seo ar an mbealach céanna go mór.

An bhfuil bloat agam?

Tá roinnt bealaí ann chun a chinneadh an bhfuil bloat agat. Is é an smaoineamh atá leis an gcéad cheann ná staitisticí inmheánacha Postgres a úsáid, ina bhfuil faisnéis neas faoi líon na sraitheanna i dtáblaí, líon na sraitheanna "beo", etc. Is féidir leat go leor éagsúlachtaí de scripteanna réamhdhéanta a fháil ar an Idirlíon. Ghlacamar mar bhonn script ó PostgreSQL Experts, ar féidir leo táblaí bloat a mheas mar aon le hinnéacsanna tósta agus bloat btree. In ár dtaithí, is é a earráid 10-20%.

Bealach eile ná an síneadh a úsáid pgstattuple, a ligeann duit breathnú taobh istigh de na leathanaigh agus luach measta agus bloat cruinn a fháil. Ach sa dara cás, beidh ort an tábla iomlán a scanadh.

Breithnímid luach bloat beag, suas le 20%, inghlactha. Is féidir é a mheas mar analóg fachtóir líonta le haghaidh táblaí и innéacsanna. Ag 50% agus níos airde, féadfaidh fadhbanna feidhmíochta tosú.

Bealaí chun troid i gcoinne bloat

Tá roinnt bealaí ag Postgres chun déileáil le bloat as an mbosca, ach níl siad oiriúnach do gach duine i gcónaí.

Cumraigh AUTOVACUUM ionas nach dtarlóidh bloat. Nó níos cruinne, é a choinneáil ag leibhéal atá inghlactha agat. Is cosúil gur comhairle “captaen” é seo, ach i ndáiríre ní bhíonn sé éasca i gcónaí é seo a bhaint amach. Mar shampla, tá forbairt ghníomhach agat le hathruithe rialta ar an scéimre sonraí, nó tá aistriú sonraí de chineál éigin ar siúl. Mar thoradh air sin, d’fhéadfadh go n-athróidh do phróifíl ualaigh go minic agus de ghnáth athróidh sé ó tábla go tábla. Ciallaíonn sé seo go gcaithfidh tú oibriú i gcónaí beagán chun tosaigh agus AUTOVACUUM a choigeartú de réir phróifíl athraitheach gach tábla. Ach is léir nach bhfuil sé seo éasca a dhéanamh.

Cúis choitianta eile nach féidir le AUTOVACUUM coinneáil leis na táblaí ná toisc go bhfuil idirbhearta fadtréimhseacha ann a chuireann cosc ​​air na sonraí atá ar fáil do na hidirbhearta sin a ghlanadh. Tá an moladh anseo soiléir freisin - fáil réidh le hidirbhearta “dangling” agus íoslaghdaigh am na n-idirbheart gníomhach. Ach má tá an t-ualach ar d'iarratas ina hibrideach de OLAP agus OLTP, ansin is féidir go leor nuashonruithe rialta agus ceisteanna gearra a bheith agat ag an am céanna, chomh maith le hoibríochtaí fadtéarmacha - mar shampla, tuarascáil a thógáil. I gcás den sórt sin, is fiú smaoineamh ar an ualach a scaipeadh thar bhoinn éagsúla, rud a cheadóidh mionchoigeartú gach ceann acu.

Sampla eile - fiú má tá an próifíl aonchineálach, ach tá an bunachar sonraí faoi ualach an-ard, ansin ní fhéadfaidh fiú an AUTOVACUUM is ionsaitheach dul i ngleic, agus tarlóidh bloat. Is é scálú (ingearach nó cothrománach) an t-aon réiteach.

Cad atá le déanamh i gcás ina bhfuil AUTOVACUUM ar bun agat, ach leanann an bloat ag fás.

Foireann Folamh IOMLÁN atógann sé inneachar na dtáblaí agus na n-innéacsanna agus ní fhágtar ach sonraí ábhartha iontu. Chun deireadh a chur le bloat, oibríonn sé go foirfe, ach le linn a fhorghníomhaithe gabhtar glas eisiach ar an tábla (AccessExclusiveLock), rud nach gceadóidh ceisteanna a fhorghníomhú ar an tábla seo, roghnaíonn sé fiú. Más féidir leat do sheirbhís nó cuid di a stopadh ar feadh tamaill (ó na deich nóiméad go dtí roinnt uaireanta ag brath ar mhéid an bhunachair shonraí agus do chrua-earraí), ansin is é an rogha seo an rogha is fearr. Ar an drochuair, níl am againn VACUUM FULL a reáchtáil le linn na cothabhála sceidealta, mar sin níl an modh seo oiriúnach dúinn.

Foireann CLUSTER Atógann sé inneachar na dtáblaí ar an mbealach céanna le FOLAMH IOMLÁN, ach ligeann duit innéacs a shonrú dá n-ordófar na sonraí go fisiciúil ar dhiosca (ach sa todhchaí níl an t-ordú ráthaithe le haghaidh sraitheanna nua). I gcásanna áirithe, is leas iomlán a bhaint é seo le haghaidh roinnt ceisteanna - le taifid iolracha a léamh de réir innéacs. Tá míbhuntáiste an ordaithe mar an gcéanna le VACUUM FULL - glasann sé an tábla le linn oibriú.

Foireann REINDEX cosúil leis an dá cheann roimhe seo, ach atógann sé innéacs sonrach nó gach innéacs den tábla. Tá glais beagán níos laige: ShareLock ar an tábla (cosc ar mhodhnuithe, ach ceadaíonn roghnú) agus AccessExclusiveLock ar an innéacs á atógáil (bloc ceisteanna ag baint úsáide as an innéacs). Mar sin féin, sa 12ú leagan de Postgres chuma paraiméadar TABHAIR FAOI DEARA, a ligeann duit an t-innéacs a atógáil gan bac a chur ar shuimiú, a mhodhnú nó a scriosadh i gcomhthráth.

I leaganacha níos luaithe de Postgres, is féidir leat toradh cosúil le REINDEX a úsáid i gcomhthráth a bhaint amach CRUTHAIGH INNÉACS FAOI LÁTHAIR. Ligeann sé duit innéacs a chruthú gan glasáil dhian (ShareUpdateExclusiveLock, nach gcuireann isteach ar cheisteanna comhthreomhara), ansin cuir ceann nua in ionad an sean-innéacs agus scrios an sean-innéacs. Ligeann sé seo duit deireadh a chur le bloat innéacs gan cur isteach ar d'iarratas. Tá sé tábhachtach a chur san áireamh nuair a bheidh innéacsanna á atógáil beidh ualach breise ar an bhfochóras diosca.

Dá bhrí sin, más rud é le haghaidh innéacsanna tá bealaí ann chun deireadh a chur le bloat "ar an eitilt," ansin níl aon cheann le haghaidh táblaí. Seo an áit a dtagann síntí seachtracha éagsúla i bhfeidhm: pg_repack (pg_reorg roimhe seo), pgcompact, pgcompacttable agus Daoine eile. San Airteagal seo, ní dhéanfaidh mé iad a chur i gcomparáid agus ní bheidh mé ag caint ach faoi pg_repack, a úsáideann muid féin, tar éis roinnt modhnú.

Conas a oibríonn pg_repack

Postgres: bloat, pg_repack agus srianta iarchurtha
Ligean le rá go bhfuil tábla go hiomlán gnáth againn - le hinnéacsanna, srianta agus, ar an drochuair, le bloat. Is é an chéad chéim de pg_repack ná tábla logála a chruthú chun sonraí a stóráil faoi gach athrú agus é ag rith. Déanfaidh an truicear na hathruithe seo a mhacasamhlú le haghaidh gach cuir isteach, nuashonrú agus scriosadh. Ansin cruthaítear tábla, cosúil leis an gceann bunaidh i struchtúr, ach gan innéacsanna agus srianta, ionas nach gcuirfear moill ar an bpróiseas chun sonraí a chur isteach.

Ansin, aistríonn pg_repack na sonraí ón sean tábla go dtí an tábla nua, ag scagadh go huathoibríoch na sraitheanna nach mbaineann le hábhar, agus ansin cruthaíonn sé innéacsanna don tábla nua. Le linn na hoibríochtaí seo go léir a chur i gcrích, carnann athruithe sa tábla logála.

Is é an chéad chéim eile ná na hathruithe a aistriú chuig an tábla nua. Déantar an t-aistriú thar roinnt atriallta, agus nuair a bhíonn níos lú ná 20 iontráil fágtha sa tábla logála, faigheann pg_repack glas láidir, aistríonn sé na sonraí is déanaí, agus cuireann sé an tábla nua in ionad an tseantábla leis an gceann nua i dtáblaí córais Postgres. Is é seo an t-aon am agus an-ghearr nuair nach mbeidh tú in ann oibriú leis an tábla. Tar éis seo, scriostar an sean tábla agus an tábla le logaí agus scaoiltear spás sa chóras comhaid. Tá an próiseas críochnaithe.

Breathnaíonn gach rud iontach go teoiriciúil, ach cad a tharlaíonn go praiticiúil? Thástáil muid pg_repack gan ualach agus faoi ualach, agus sheiceáil muid a oibriú i gcás stad roimh am (i bhfocail eile, ag baint úsáide as Ctrl+C). Bhí na tástálacha go léir dearfach.

Chuamar go dtí an siopa bia - agus ansin níor chuaigh gach rud mar a bhí súil againn.

An chéad pancóg ar díol

Ar an gcéad bhraisle fuaireamar earráid maidir le sárú ar shriantacht uathúil:

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

Bhí innéacs ainm uathghinte ag an teorainn seo_16508 - chruthaigh pg_repack é. Bunaithe ar na tréithe atá san áireamh ina chomhdhéanamh, chinneamar an srian “ár” a fhreagraíonn dó. Ba í an fhadhb a bhí ann ná nach gnáth-theorannú é seo, ach teorainn iarchurtha (srian iarchurtha), i.e. déantar a fhíorú níos déanaí ná an t-ordú sql, rud a fhágann iarmhairtí gan choinne.

Srianta iarchurtha: cén fáth a bhfuil gá leo agus conas a oibríonn siad

Teoiric bheag faoi shrianta iarchurtha.
Breathnaímid ar shampla simplí: tá leabhar tagartha do ghluaisteáin againn le dhá thréith - ainm agus ord an ghluaisteáin san eolaire.
Postgres: bloat, pg_repack agus srianta iarchurtha

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



Ligean le rá gur ghá dúinn an chéad agus an dara carr a mhalartú. Is é an réiteach simplí ná an chéad luach a nuashonrú go dtí an dara ceann, agus an dara ceann go dtí an chéad:

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

Ach nuair a ritheann muid an cód seo, táimid ag súil le sárú srianta toisc go bhfuil ord na luachanna sa tábla uathúil:

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

Conas is féidir liom é a dhéanamh ar bhealach difriúil? Rogha a haon: luach athsholáthair breise a chur le hordú a ráthaítear nach bhfuil sa tábla, mar shampla “-1”. I gclárú, tugtar "luachanna dhá athróg a mhalartú trí thrian." Is é an t-aon mhíbhuntáiste a bhaineann leis an modh seo ná an nuashonrú breise.

Rogha a dó: Athdhear an tábla chun cineál sonraí snámhphointe a úsáid don luach ordaithe in ionad slánuimhreacha. Ansin, agus an luach á nuashonrú ó 1, mar shampla, go 2.5, beidh an chéad iontráil "seasamh" go huathoibríoch idir an dara agus an tríú. Oibríonn an réiteach seo, ach tá dhá theorainn ann. Ar dtús, ní oibreoidh sé duit má úsáidtear an luach áit éigin sa chomhéadan. Ar an dara dul síos, ag brath ar chruinneas an chineáil sonraí, beidh líon teoranta cuir isteach féideartha agat sula ndéantar luachanna na dtaifead go léir a athríomh.

Rogha a trí: an srian a chur siar ionas nach ndéanfar é a sheiceáil ach amháin nuair a dhéanfar é a ghealladh:

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

Ós rud é go gcinntíonn loighic ár n-iarratas tosaigh go bhfuil gach luach uathúil tráth an ghealltanais, éireoidh leis.

Tá an sampla a pléadh thuas, ar ndóigh, an-sintéiseach, ach nochtann sé an smaoineamh. In ár n-iarratas, bainimid úsáid as srianta iarchurtha chun loighic a chur i bhfeidhm atá freagrach as coinbhleachtaí a réiteach nuair a oibríonn úsáideoirí ag an am céanna le rudaí giuirléidí roinnte ar an gclár. Trí úsáid a bhaint as srianta den sórt sin is féidir linn an cód iarratais a dhéanamh beagán níos simplí.

Go ginearálta, ag brath ar an gcineál srianta, tá trí leibhéal granularity ag Postgres chun iad a sheiceáil: leibhéil as a chéile, idirbhirt agus slonn.
Postgres: bloat, pg_repack agus srianta iarchurtha
Foinse: begriffs

CHECK and NOT NULL a sheiceáil ag an leibhéal ró; i gcás srianta eile, mar atá le feiceáil sa tábla, tá roghanna éagsúla. Is féidir leat níos mó a léamh anseo.

Mar achoimre achomair, cuireann srianta iarchurtha cód níos inléite agus níos lú orduithe ar fáil i gcásanna áirithe. Mar sin féin, caithfidh tú íoc as seo tríd an bpróiseas dífhabhtaithe casta a dhéanamh, ós rud é go bhfuil an nóiméad a tharlaíonn an earráid agus an nóiméad a fhaigheann tú amach faoi scartha in am. Fadhb eile a d’fhéadfadh a bheith ann ná go mb’fhéidir nach mbeidh an sceidealóir in ann plean barrmhaith a dhéanamh i gcónaí má bhíonn srian iarchurtha i gceist leis an iarratas.

Feabhsú pg_repack

D'fholaíomar cad iad na srianta iarchurtha, ach cén bhaint atá acu lenár bhfadhb? Cuimhnímis ar an earráid a fuaireamar níos luaithe:

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

Tarlaíonn sé nuair a chóipeáiltear sonraí ó thábla logála go tábla nua. Breathnaíonn sé seo aisteach mar ... tá na sonraí sa tábla loga geallta mar aon leis na sonraí sa tábla foinse. Má shásaíonn siad srianta an bhuntábla, conas is féidir leo na srianta céanna a shárú sa cheann nua?

Mar a tharla sé, luíonn fréamh na faidhbe sa chéim roimhe seo de pg_repack, rud a chruthaíonn innéacsanna amháin, ach ní srianta: bhí srian uathúil ar an sean tábla, agus chruthaigh an ceann nua innéacs uathúil ina ionad.

Postgres: bloat, pg_repack agus srianta iarchurtha

Tá sé tábhachtach a thabhairt faoi deara anseo, má tá an srian gnáth agus nach gcuirtear siar é, go bhfuil an t-innéacs uathúil cruthaithe ina ionad sin comhionann leis an srian seo, mar gheall ar Cuirtear srianta uathúla i Postgres i bhfeidhm trí innéacs uathúil a chruthú. Ach i gcás srianta iarchurtha, níl an iompar mar an gcéanna, toisc nach féidir an t-innéacs a chur siar agus déantar é a sheiceáil i gcónaí ag an am a dhéantar an t-ordú sql a fhorghníomhú.

Mar sin, luíonn croílár na faidhbe i “moill” an tseic: sa tábla bunaidh tarlaíonn sé tráth an ghealltanais, agus sa tábla nua ag an am a dhéantar an t-ordú sql. Ciallaíonn sé seo go gcaithfimid a chinntiú go ndéantar na seiceálacha mar an gcéanna sa dá chás: bíodh moill orthu i gcónaí, nó láithreach i gcónaí.

Mar sin, cad iad na smaointe a bhí againn?

Cruthaigh innéacs cosúil leis an iarchurtha

Is é an chéad smaoineamh an dá sheiceáil a dhéanamh i mód láithreach. Féadfaidh sé seo roinnt srianta dearfacha bréagacha a ghiniúint, ach mura bhfuil mórán acu ann, níor cheart go gcuirfeadh sé seo isteach ar obair na n-úsáideoirí, ós rud é gur gnáthchás dóibh coinbhleachtaí den sórt sin. Tarlaíonn siad, mar shampla, nuair a thosaíonn beirt úsáideoir ag eagarthóireacht an ghiuirléid chéanna ag an am céanna, agus níl am ag cliant an dara úsáideoir faisnéis a fháil go bhfuil an ghiuirléid bactha cheana féin le haghaidh eagarthóireachta ag an gcéad úsáideoir. I gcás den sórt sin, diúltaíonn an freastalaí an dara úsáideoir, agus rollaíonn a chliant ar ais na hathruithe agus bloic an ghiuirléid. Beagán níos déanaí, nuair a chríochnaíonn an chéad úsáideoir eagarthóireacht, gheobhaidh an dara ceann faisnéis nach bhfuil bac ar an ngiuirléid a thuilleadh agus beidh siad in ann a ngníomh a dhéanamh arís.

Postgres: bloat, pg_repack agus srianta iarchurtha

Chun a chinntiú go mbíonn seiceálacha i mód neamh-iarchurtha i gcónaí, chruthaíomar innéacs nua cosúil leis an srian iarchurtha bunaidh:

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

Sa timpeallacht tástála, ní bhfuaireamar ach cúpla earráid ionchais. Rath! Rith muid pg_repack arís ar tháirgeadh agus fuair muid 5 earráid ar an gcéad bhraisle in uair an chloig oibre. Is toradh inghlactha é seo. Mar sin féin, cheana féin ar an dara braisle tháinig méadú suntasach ar líon na n-earráidí agus bhí orainn stop a chur le pg_repack.

Cén fáth ar tharla sé? Braitheann an dóchúlacht go dtarlóidh earráid ar cé mhéad úsáideoir atá ag obair leis na giuirléidí céanna ag an am céanna. De réir dealraimh, ag an nóiméad sin bhí i bhfad níos lú athruithe iomaíocha leis na sonraí a stóráiltear ar an gcéad bhraisle ná mar a bhí ar na cinn eile, i.e. ní raibh ach “ádh” orainn.

Níor oibrigh an smaoineamh. Ag an bpointe sin, chonaiceamar dhá réiteach eile: ár gcód iarratais a athscríobh chun srianta iarchurtha a fhágáil ar lár, nó “teach” pg_repack chun oibriú leo. Roghnaigh muid an dara ceann.

Cuir srianta iarchurtha ón tábla bunaidh in ionad innéacsanna sa tábla nua

Bhí cuspóir an athbhreithnithe soiléir - má tá srian iarchurtha ag an tábla bunaidh, ansin don cheann nua is gá duit srian den sórt sin a chruthú, agus ní innéacs.

Chun ár n-athruithe a thástáil, scríobhamar tástáil shimplí:

  • tábla le srian iarchurtha agus taifead amháin;
  • sonraí a chur isteach i lúb a thagann salach ar thaifead reatha;
  • nuashonrú a dhéanamh – ní thagann salachar ar na sonraí a thuilleadh;
  • tiomantas a thabhairt do na hathruithe.

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;

Thit an bunleagan de pg_repack i gcónaí ar an gcéad chur isteach, d'oibrigh an leagan modhnaithe gan earráidí. Go hiontach.

Téimid chuig táirgeadh agus faighimid earráid arís ag an gcéim chéanna de chóipeáil sonraí ón tábla logála chuig ceann nua:

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

Staid clasaiceach: oibríonn gach rud i dtimpeallachtaí tástála, ach ní i dtáirgeadh?!

APPLY_COUNT agus acomhal dhá bhaisc

Thosaigh muid ag déanamh anailíse litriúil ar an gcód de réir líne agus fuaireamar amach pointe tábhachtach: aistrítear sonraí ón tábla logála go dtí ceann nua i mbaisceanna, léirigh an tairiseach APPLY_COUNT méid an bhaisc:

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

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

Is í an fhadhb atá ann ná go bhféadfaidh na sonraí ón idirbheart bunaidh, ina bhféadfadh roinnt oibríochtaí an srian a shárú, nuair a aistrítear iad, ag acomhal dhá bhaisc - déanfar leath na n-orduithe sa chéad bhaisc, agus an leath eile. sa dara. Agus anseo, ag brath ar do luck: mura sáraíonn na foirne rud ar bith sa chéad bhaisc, ansin tá gach rud go breá, ach má dhéanann siad, tarlaíonn earráid.

Is ionann APPLY_COUNT agus 1000 taifead, a mhíníonn cén fáth ar éirigh lenár dtástálacha - níor chlúdaigh siad cás na “batchacomhal”. D'úsáideamar dhá ordú - cuir isteach agus nuashonraigh, mar sin cuireadh go díreach 500 idirbheart de dhá ordú i mbaisc i gcónaí agus ní raibh aon fhadhbanna againn. Tar éis an dara nuashonrú a chur leis, stop ár n-eagar ag obair:

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;

Mar sin, is é an chéad tasc eile ná a chinntiú go gcríochnaíonn sonraí ón tábla bunaidh, a athraíodh in idirbheart amháin, sa tábla nua freisin laistigh d'idirbheart amháin.

Diúltú ó bhaisc

Agus arís bhí dhá réiteach againn. Gcéad dul síos: a ligean ar thréigean go hiomlán deighilt i mbaisceanna agus sonraí a aistriú in aon idirbheart amháin. Ba é an buntáiste a bhaineann leis an réiteach seo ná a simplíocht - ní raibh mórán athruithe ar an gcód ag teastáil (dála an scéil, i leaganacha níos sine d'oibrigh pg_reorg go díreach mar sin). Ach tá fadhb ann - táimid ag cruthú idirbheart fadtéarmach, agus tá sé seo, mar a dúradh cheana, ina bhagairt ar theacht chun cinn bloat nua.

Tá an dara réiteach níos casta, ach is dócha go bhfuil sé níos ceart: cruthaigh colún sa tábla logála le haitheantóir an idirbhirt a chuir sonraí leis an tábla. Ansin, nuair a dhéanaimid sonraí a chóipeáil, is féidir linn é a ghrúpáil de réir an tréith seo agus a chinntiú go n-aistrítear athruithe gaolmhara le chéile. Cruthófar an bhaisc ó roinnt idirbheart (nó idirbheart mór amháin) agus athróidh a méid ag brath ar an méid sonraí a athraíodh sna hidirbhearta sin. Tá sé tábhachtach a thabhairt faoi deara, ós rud é go gcuireann sonraí ó idirbhearta éagsúla isteach sa tábla logála in ord randamach, ní bheidh sé indéanta a thuilleadh é a léamh go seicheamhach, mar a bhí roimhe seo. seqscan do gach iarratas le scagadh ag tx_id ró-chostasach, tá gá le hinnéacs, ach beidh sé mall síos freisin ar an modh mar gheall ar an forchostais a nuashonrú. Go ginearálta, mar i gcónaí, ní mór duit rud éigin a íobairt.

Mar sin, shocraigh muid tús a chur leis an gcéad rogha, toisc go bhfuil sé níos simplí. Ar dtús, ba ghá a thuiscint an mbeadh idirbheart fada ina fhíorfhadhb. Ós rud é go dtarlaíonn an t-aistriú is mó sonraí ón sean tábla go dtí an ceann nua in aon idirbheart fada amháin, chlaochlú an cheist go "cé mhéid a mhéadóimid an t-idirbheart seo?" Braitheann fad an chéad idirbheart go príomha ar mhéid an tábla. Braitheann fad ceann nua ar cé mhéad athruithe a charnaítear sa tábla le linn an aistrithe sonraí, i.e. ar dhéine an ualaigh. Tharla an rith pg_repack le linn ualach seirbhíse íosta, agus bhí méid na n-athruithe go díréireach beag i gcomparáid le méid bunaidh an tábla. Shocraigh muid go bhféadfaimis faillí a dhéanamh ar am idirbhirt nua (le haghaidh comparáide, is é 1 uair an chloig agus 2-3 nóiméad ar an meán).

Bhí na turgnaimh dearfach. Seoladh ar tháirgeadh freisin. Ar mhaithe le soiléireacht, seo pictiúr leis an méid de cheann de na bunachair shonraí tar éis rith:

Postgres: bloat, pg_repack agus srianta iarchurtha

Ós rud é go raibh muid sásta go hiomlán leis an réiteach seo, ní dhearna muid iarracht an dara ceann a chur i bhfeidhm, ach táimid ag smaoineamh ar an bhféidearthacht é a phlé leis na forbróirí síneadh. Ar an drochuair, níl an t-athbhreithniú atá againn faoi láthair réidh le foilsiú go fóill, mar níor réitigh muid ach an fhadhb le srianta uathúla iarchurtha, agus le haghaidh paiste lán-chuimsitheach is gá tacaíocht a sholáthar do chineálacha eile. Tá súil againn go mbeimid in ann é seo a dhéanamh amach anseo.

B’fhéidir go bhfuil ceist agat, cén fáth a raibh baint againn fiú leis an scéal seo le modhnú pg_repack, agus nár úsáideamar, mar shampla, a chuid analógacha? Ag pointe éigin smaoinigh muid faoi seo freisin, ach spreag an taithí dhearfach ar é a úsáid níos luaithe, ar tháblaí gan srianta iarchurtha, sinn chun iarracht a dhéanamh croílár na faidhbe a thuiscint agus a shocrú. Ina theannta sin, teastaíonn am chun tástálacha a dhéanamh le réitigh eile a úsáid, agus mar sin shocraigh muid go ndéanfaimis iarracht ar dtús an fhadhb a réiteach, agus dá dtuigfimid nach bhféadfaimis é seo a dhéanamh laistigh de thréimhse réasúnta ama, ansin thosaíomar ag féachaint ar analógacha. .

Torthaí

Cad is féidir linn a mholadh bunaithe ar ár dtaithí féin:

  1. Monatóireacht a dhéanamh ar do bloat. Bunaithe ar shonraí monatóireachta, is féidir leat a thuiscint cé chomh maith is atá autovacuum cumraithe.
  2. Coigeartaigh AUTOVACUUM chun bloat a choinneáil ag leibhéal inghlactha.
  3. Má tá an bloat fós ag fás agus nach féidir leat é a shárú le huirlisí lasmuigh den bhosca, ná bíodh eagla ort síntí seachtracha a úsáid. Is é an rud is mó ná gach rud a thástáil go maith.
  4. Ná bíodh eagla ort réitigh sheachtracha a mhodhnú chun freastal ar do chuid riachtanas - uaireanta is féidir é seo a bheith níos éifeachtaí agus níos éasca fós ná do chód féin a athrú.

Foinse: will.com

Add a comment