Postgres: bloat, pg_repack ak kontrent difere

Postgres: bloat, pg_repack ak kontrent difere

Efè gonfleman sou tab ak endèks se lajman li te ye epi li prezan pa sèlman nan Postgres. Gen fason pou fè fas ak li soti nan bwat la, tankou VACUUM FULL oswa CLUSTER, men yo fèmen tab pandan operasyon an epi kidonk yo pa ka toujou itilize.

Atik la pral gen yon ti teyori sou fason gonfleman rive, ki jan ou ka goumen kont li, sou kontrent difere ak pwoblèm yo pote nan itilizasyon ekstansyon pg_repack la.

Atik sa a ekri baze sou diskou mwen nan PgConf.Russia 2020.

Poukisa gonfleman rive?

Postgres baze sou yon modèl milti-vèsyon (MVCC). Sans li se ke chak ranje nan tablo a ka gen plizyè vèsyon, pandan y ap tranzaksyon yo pa wè plis pase youn nan vèsyon sa yo, men se pa nesesèman menm yon sèl la. Sa a pèmèt plizyè tranzaksyon yo travay ansanm epi yo pa gen nòmalman enpak youn sou lòt.

Li evidan, tout vèsyon sa yo bezwen yo dwe estoke. Postgres travay ak memwa paj pa paj ak yon paj se kantite minimòm done ki ka li nan disk oswa ekri. Ann gade yon ti egzanp pou w konprann ki jan sa rive.

Ann di nou gen yon tab kote nou te ajoute plizyè dosye. Nouvo done parèt nan premye paj dosye a kote tab la estoke. Sa yo se vèsyon vivan nan ranje ki disponib nan lòt tranzaksyon apre yon komèt (pou senplisite, nou pral asime ke nivo izolasyon an se Read Committed).

Postgres: bloat, pg_repack ak kontrent difere

Lè sa a, nou mete ajou youn nan antre yo, kidonk make ansyen vèsyon an kòm pa enpòtan ankò.

Postgres: bloat, pg_repack ak kontrent difere

Etap pa etap, mete ajou ak efase vèsyon ranje, nou te fini ak yon paj nan ki apeprè mwatye nan done yo se "fatra". Done sa yo pa vizib pou okenn tranzaksyon.

Postgres: bloat, pg_repack ak kontrent difere

Postgres gen yon mekanis Vakyòm, ki netwaye vèsyon demode epi fè plas pou nouvo done. Men, si li pa configured ase agresif oswa li okipe travay nan lòt tab, Lè sa a, "done fatra" rete, epi nou dwe itilize paj adisyonèl pou nouvo done.

Se konsa, nan egzanp nou an, nan kèk pwen nan tan tab la ap konpoze de kat paj, men se sèlman mwatye nan li pral gen done vivan. Kòm yon rezilta, lè w ap jwenn aksè nan tab la, nou pral li plis done pase sa nesesè.

Postgres: bloat, pg_repack ak kontrent difere

Menm si VACUUM kounye a efase tout vèsyon ranje ki pa enpòtan, sitiyasyon an pa pral amelyore dramatikman. Nou pral gen espas gratis nan paj oswa menm paj antye pou nouvo ranje, men nou pral toujou ap li plis done pase sa nesesè.
By wout la, si yon paj konplètman vid (dezyèm youn nan nan egzanp nou an) te nan fen dosye a, Lè sa a, VACUUM ta kapab taye li. Men, kounye a li nan mitan an, kidonk pa gen anyen ki ka fè ak li.

Postgres: bloat, pg_repack ak kontrent difere

Lè kantite paj sa yo vid oswa trè rar vin gwo, ki rele gonfleman, li kòmanse afekte pèfòmans.

Tout sa ki dekri pi wo a se mekanik yo nan ensidan an nan gonfleman nan tab. Nan endèks sa rive nan anpil menm jan an.

Èske mwen gen gonfleman?

Gen plizyè fason pou detèmine si ou gen gonfleman. Lide a nan premye a se sèvi ak estatistik entèn Postgres, ki gen enfòmasyon apwoksimatif sou kantite ranje nan tab, kantite ranje "viv", elatriye Ou ka jwenn anpil varyasyon nan Scripts pare sou entènèt la. Nou te pran kòm yon baz script soti nan Ekspè PostgreSQL, ki ka evalye tab bloat ansanm ak griye ak endèks bloat btree. Nan eksperyans nou an, erè li yo se 10-20%.

Yon lòt fason se sèvi ak ekstansyon an pgstattuple, ki pèmèt ou gade andedan paj yo epi jwenn tou de yon valè estime ak yon valè egzak. Men, nan dezyèm ka a, ou pral oblije tcheke tout tab la.

Nou konsidere yon ti valè bloat, jiska 20%, akseptab. Li kapab konsidere kòm yon analogue de fillfactor pou tab и endis. Nan 50% ak pi wo, pwoblèm pèfòmans yo ka kòmanse.

Fason pou konbat gonfleman

Postgres gen plizyè fason pou fè fas ak gonfleman soti nan bwat la, men yo pa toujou apwopriye pou tout moun.

Konfigure AUTOVACUUM pou gonfleman pa rive. Oswa plis jisteman, kenbe li nan yon nivo akseptab pou ou. Sa a sanble tankou konsèy "kapitèn nan", men an reyalite sa a se pa toujou fasil reyalize. Pou egzanp, ou gen devlopman aktif ak chanjman regilye nan chema done a, oswa kèk kalite migrasyon done k ap fèt. Kòm yon rezilta, pwofil chaj ou a ka chanje souvan epi yo pral tipikman varye de tab an tab. Sa vle di ou bezwen toujou ap travay yon ti kras pi devan epi ajiste AUTOVACUUM nan pwofil la chanje nan chak tab. Men, evidamman sa a se pa fasil fè.

Yon lòt rezon komen poukisa AUTOVACUUM pa ka kenbe ak tab yo se paske gen tranzaksyon ki dire lontan ki anpeche li netwaye done ki disponib nan tranzaksyon sa yo. Rekòmandasyon isit la tou evidan - debarase m de tranzaksyon "pandan" epi minimize tan tranzaksyon aktif yo. Men, si chaj la sou aplikasyon w lan se yon ibrid nan OLAP ak OLTP, Lè sa a, ou ka ansanm gen anpil mizajou souvan ak demann kout, osi byen ke operasyon alontèm - pou egzanp, bati yon rapò. Nan yon sitiyasyon konsa, li vo panse sou gaye chay la atravè diferan baz, ki pral pèmèt pou plis amann-akor nan chak nan yo.

Yon lòt egzanp - menm si pwofil la se omojèn, men baz done a se anba yon chaj trè wo, Lè sa a, menm AUTOVACUUM ki pi agresif pa ka fè fas, ak gonfleman pral rive. Echèl (vètikal oswa orizontal) se solisyon an sèlman.

Kisa pou w fè nan yon sitiyasyon kote ou te mete kanpe AUTOVACUUM, men gonfleman an kontinye ap grandi.

Ekip VACUUM PLEN rebati sa ki nan tab yo ak endèks epi kite sèlman done ki enpòtan nan yo. Pou elimine gonfleman, li travay parfe, men pandan ekzekisyon li yo se yon seri eksklizif sou tab la kaptire (AccessExclusiveLock), ki pa pral pèmèt egzekite demann sou tab sa a, menm chwazi. Si ou gen mwayen pou sispann sèvis ou oswa yon pati nan li pou kèk tan (soti nan dè dizèn de minit ak plizyè èdtan depann sou gwosè a nan baz done a ak pyès ki nan konpitè ou), Lè sa a, opsyon sa a se pi bon an. Malerezman, nou pa gen tan kouri VACUUM FULL pandan antretyen pwograme a, kidonk metòd sa a pa apwopriye pou nou.

Ekip KLUSTER Rebati sa ki nan tab yo menm jan ak VACUUM FULL, men pèmèt ou presize yon endèks dapre ki done yo pral fizikman bay lòd sou disk (men nan lavni lòd la pa garanti pou nouvo ranje). Nan sèten sitiyasyon, sa a se yon bon optimize pou yon kantite demann - ak lekti plizyè dosye pa endèks. Dezavantaj nan lòd la se menm ak sa yo ki nan VACUUM FULL - li fèmen tab la pandan operasyon an.

Ekip REINDEX menm jan ak de anvan yo, men rebati yon endèks espesifik oswa tout endèks nan tab la. Locks yo yon ti kras pi fèb: ShareLock sou tab la (anpeche modifikasyon, men pèmèt chwazi) ak AccessExclusiveLock sou endèks la ke yo te rebati (blòk demann lè l sèvi avèk endèks sa a). Sepandan, nan vèsyon an 12th Postgres yon paramèt parèt KONTANTAN, ki pèmèt ou rebati endèks la san yo pa bloke adisyon konkouran, modifikasyon oswa efase dosye yo.

Nan vèsyon pi bonè nan Postgres, ou ka reyalize yon rezilta ki sanble ak REINDEX AK TANTANTAN lè l sèvi avèk KREYE ENDEX TANKAN. Li pèmèt ou kreye yon endèks san bloke strik (ShareUpdateExclusiveLock, ki pa entèfere ak demann paralèl), Lè sa a, ranplase ansyen endèks la ak yon nouvo epi efase ansyen endèks la. Sa a pèmèt ou elimine endèks gonfleman san yo pa entèfere ak aplikasyon w lan. Li enpòtan pou konsidere ke lè rebati endèks pral gen yon chaj adisyonèl sou subsistèm ki gen kapasite a.

Kidonk, si pou endèks gen fason pou elimine gonfleman "sou vole a," Lè sa a, pa gen okenn pou tab. Sa a se kote divès ekstansyon ekstèn antre nan jwèt: pg_repack (ansyen pg_reorg), pgcompact, pgcompacttable ak lòt moun. Nan atik sa a, mwen pa pral konpare yo epi mwen pral sèlman pale sou pg_repack, ki, apre kèk modifikasyon, nou itilize tèt nou.

Ki jan pg_repack travay

Postgres: bloat, pg_repack ak kontrent difere
Ann di nou gen yon tab konplètman òdinè - ak endèks, restriksyon ak, malerezman, ak gonfleman. Premye etap pg_repack se kreye yon tablo boutèy demi lit pou estoke done sou tout chanjman pandan li ap kouri. Deklanche a pral repwodui chanjman sa yo pou chak mete, mete ajou ak efase. Lè sa a, yo kreye yon tab, menm jan ak yon sèl orijinal la nan estrikti, men san yo pa endèks ak restriksyon, se konsa yo pa ralanti pwosesis la nan mete done.

Apre sa, pg_repack transfere done ki soti nan ansyen tab la nan nouvo tab la, otomatikman filtre tout ranje ki pa enpòtan, epi li kreye endèks pou nouvo tab la. Pandan ekzekisyon tout operasyon sa yo, chanjman yo akimile nan tablo boutèy la.

Pwochen etap la se transfere chanjman yo nan nouvo tab la. Migrasyon an fèt sou plizyè iterasyon, epi lè gen mwens pase 20 antre ki rete nan tablo log la, pg_repack jwenn yon seri gwo, imigre dènye done yo, epi ranplase ansyen tablo a ak nouvo nan tablo sistèm Postgres yo. Sa a se tan an sèlman ak trè kout lè ou pa yo pral kapab travay ak tab la. Apre sa, ansyen tab la ak tab la ak mòso bwa yo efase epi yo libere espas nan sistèm dosye a. Pwosesis la fini.

Tout bagay sanble gwo nan teyori, men sa k ap pase nan pratik? Nou teste pg_repack san chaj ak anba chaj, epi tcheke operasyon li an ka ta gen yon sispann twò bonè (nan lòt mo, lè l sèvi avèk Ctrl + C). Tout tès yo te pozitif.

Nou te ale nan magazen an manje - ak Lè sa a, tout bagay pa t 'ale jan nou te espere.

Premye galèt sou vant

Sou premye gwoup la nou te resevwa yon erè konsènan yon vyolasyon yon kontrent inik:

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

Limit sa a te gen yon non oto-pwodwi index_16508 - li te kreye pa pg_repack. Baze sou atribi ki enkli nan konpozisyon li yo, nou detèmine kontrent "nou an" ki koresponn ak li. Pwoblèm lan te tounen ke sa a se pa yon limit konplètman òdinè, men yon sèl difere (kontrent difere), sa vle di se verifikasyon li yo fèt pita pase lòd sql la, ki mennen nan konsekans inatandi.

Kontrent difere: poukisa yo bezwen ak ki jan yo travay

Yon ti teyori sou restriksyon difere.
Ann konsidere yon egzanp senp: nou gen yon liv tab-referans machin ak de atribi - non an ak lòd nan machin nan nan anyè a.
Postgres: bloat, pg_repack ak kontrent difere

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



Ann di nou te bezwen chanje machin yo premye ak dezyèm. Solisyon an senp se mete ajou premye valè a nan dezyèm lan, ak dezyèm nan premye a:

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

Men, lè nou kouri kòd sa a, nou espere yon vyolasyon kontrent paske lòd valè yo nan tablo a inik:

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

Kouman mwen ka fè li yon fason diferan? Opsyon youn: ajoute yon ranplasman valè adisyonèl nan yon lòd ki garanti pa egziste nan tablo a, pou egzanp "-1". Nan pwogramasyon, yo rele sa "echanj valè de varyab nan yon twazyèm." Sèl dezavantaj metòd sa a se aktyalizasyon adisyonèl la.

Opsyon de: Redesine tab la pou itilize yon kalite done pwen k ap flote pou valè lòd la olye pou yo nonm antye. Lè sa a, lè mete ajou valè a soti nan 1, pou egzanp, a 2.5, premye antre a pral otomatikman "kanpe" ant dezyèm ak twazyèm lan. Solisyon sa a ap travay, men gen de limit. Premyèman, li pa pral travay pou ou si valè a itilize yon kote nan koòdone la. Dezyèmman, depann sou presizyon nan kalite done a, ou pral gen yon kantite limite nan foure posib anvan rekalkile valè yo nan tout dosye.

Opsyon twa: fè kontrent la difere pou ke li tcheke sèlman nan moman an komèt:

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

Depi lojik demann inisyal nou an asire ke tout valè yo inik nan moman komèt la, li pral reyisi.

Egzanp ki diskite pi wo a se, nan kou, trè sentetik, men li revele lide a. Nan aplikasyon nou an, nou itilize kontrent difere pou aplike lojik ki responsab pou rezoud konfli lè itilizatè yo travay ansanm ak objè widget pataje sou tablo a. Sèvi ak restriksyon sa yo pèmèt nou fè kòd aplikasyon an yon ti kras pi senp.

An jeneral, tou depann de kalite kontrent, Postgres gen twa nivo granularite pou tcheke yo: ranje, tranzaksyon, ak nivo ekspresyon.
Postgres: bloat, pg_repack ak kontrent difere
Sous: begriffs

CHECK ak NOT NULL yo toujou tcheke nan nivo ranje a; pou lòt restriksyon, jan yo ka wè nan tablo a, gen diferan opsyon. Ou ka li plis isit la.

Pou rezime yon ti tan, kontrent difere nan yon kantite sitiyasyon bay plis kòd lizib ak mwens kòmandman. Sepandan, ou dwe peye pou sa a pa konplike pwosesis la debogaj, depi moman sa a erè a rive ak moman sa a ou jwenn enfòmasyon sou li yo separe nan tan. Yon lòt pwoblèm posib se ke orè a pa toujou kapab konstwi yon plan optimal si demann lan enplike yon kontrent difere.

Amelyorasyon pg_repack

Nou te kouvri ki kontrent difere yo ye, men ki jan yo gen rapò ak pwoblèm nou an? Ann sonje erè nou te resevwa pi bonè a:

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

Li rive lè yo kopye done ki soti nan yon tab boutèy demi lit nan yon nouvo tab. Sa sanble etranj paske... done ki nan tablo boutèy la komèt ansanm ak done ki nan tablo sous la. Si yo satisfè kontrent yo nan tablo orijinal la, ki jan yo ka vyole kontrent yo menm nan nouvo a?

Kòm li vire soti, rasin nan pwoblèm nan manti nan etap anvan an nan pg_repack, ki kreye sèlman endèks, men se pa kontrent: ansyen tab la te gen yon kontrent inik, ak yon sèl la nouvo te kreye yon endèks inik olye.

Postgres: bloat, pg_repack ak kontrent difere

Li enpòtan pou sonje isit la ke si kontrent la nòmal epi li pa difere, Lè sa a, endèks inik ki te kreye olye de sa a ekivalan a kontrent sa a, paske Kontrent inik nan Postgres yo aplike lè yo kreye yon endèks inik. Men, nan ka yon kontrent difere, konpòtman an pa menm, paske endèks la pa ka difere epi yo toujou tcheke nan moman an sql lòd la egzekite.

Kidonk, sans nan pwoblèm nan manti nan "reta" nan chèk la: nan tablo orijinal la li rive nan moman an nan komèt, ak nan tablo a nouvo nan moman an sql lòd la egzekite. Sa vle di nou bezwen asire w ke chèk yo fèt menm jan an nan tou de ka yo: swa toujou reta, oswa toujou imedyatman.

Se konsa, ki lide nou te genyen?

Kreye yon endèks ki sanble ak difere

Premye lide a se fè tou de chèk nan mòd imedya. Sa a ka jenere plizyè restriksyon fo pozitif, men si gen kèk nan yo, sa pa ta dwe afekte travay itilizatè yo, paske konfli sa yo se yon sitiyasyon nòmal pou yo. Yo rive, pou egzanp, lè de itilizatè kòmanse modifye menm widje a an menm tan, ak kliyan an nan dezyèm itilizatè a pa gen tan resevwa enfòmasyon ke widje a deja bloke pou koreksyon pa itilizatè a premye. Nan yon sitiyasyon konsa, sèvè a refize dezyèm itilizatè a, epi kliyan li yo retounen chanjman yo epi bloke widget la. Yon ti kras pita, lè premye itilizatè a fini koreksyon, dezyèm lan pral resevwa enfòmasyon ke widje a pa bloke ankò epi yo pral kapab repete aksyon yo.

Postgres: bloat, pg_repack ak kontrent difere

Pou asire ke chèk yo toujou nan mòd ki pa difere, nou te kreye yon nouvo endèks ki sanble ak kontrent difere orijinal la:

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

Nan anviwònman tès la, nou te resevwa sèlman kèk erè espere. Siksè! Nou te kouri pg_repack ankò sou pwodiksyon epi nou te resevwa 5 erè sou premye gwoup la nan yon èdtan nan travay. Sa a se yon rezilta akseptab. Sepandan, deja sou dezyèm gwoup la kantite erè te ogmante anpil e nou te oblije sispann pg_repack.

Poukisa sa te rive? Pwobabilite pou yon erè rive depann de konbyen itilizatè k ap travay ak menm widgets yo an menm tan. Aparamman, nan moman sa a te gen anpil mwens chanjman konpetitif ak done ki estoke sou premye gwoup la pase sou lòt yo, i.e. nou te jis "chans".

Lide a pa t mache. Nan pwen sa a, nou te wè de lòt solisyon: reekri kòd aplikasyon nou an pou dispanse kontrent difere, oswa "anseye" pg_repack pou travay avèk yo. Nou te chwazi dezyèm lan.

Ranplase endèks nan nouvo tablo a ak kontrent difere soti nan tablo orijinal la

Objektif revizyon an te evidan - si tab orijinal la gen yon kontrent difere, Lè sa a, pou nouvo nan ou bezwen kreye tankou yon kontrent, epi yo pa yon endèks.

Pou teste chanjman nou yo, nou te ekri yon tès senp:

  • tab ki gen yon kontrent difere ak yon dosye;
  • mete done nan yon bouk ki konfli ak yon dosye ki deja egziste;
  • fè yon aktyalizasyon - done yo pa gen konfli ankò;
  • komèt chanjman yo.

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;

Vèsyon orijinal la nan pg_repack toujou fè aksidan sou insert an premye, vèsyon an modifye te travay san erè. Gwo.

Nou ale nan pwodiksyon epi ankò jwenn yon erè nan menm faz la nan kopye done ki soti nan tab la boutèy demi lit nan yon nouvo:

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

Sitiyasyon klasik: tout bagay ap travay nan anviwònman tès, men se pa nan pwodiksyon?!

APPLY_COUNT ak junction de pakèt

Nou te kòmanse analize kòd la literalman liy pa liy epi nou te dekouvri yon pwen enpòtan: done yo transfere soti nan tablo boutèy la nan yon nouvo nan pakèt, konstan APPLY_COUNT la endike gwosè pakèt la:

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

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

Pwoblèm lan se ke done ki soti nan tranzaksyon orijinal la, nan ki plizyè operasyon ta ka potansyèlman vyole kontrent la, lè yo transfere, ka fini nan junction a nan de lo - mwatye nan kòmandman yo pral komèt nan premye pakèt la, ak lòt mwatye a. nan dezyèm lan. Ak isit la, tou depann de chans ou: si ekip yo pa vyole anyen nan premye pakèt la, Lè sa a, tout bagay anfòm, men si yo fè sa, yon erè rive.

APPLY_COUNT egal a 1000 dosye, ki eksplike poukisa tès nou yo te reyisi - yo pa t kouvri ka "junction pakèt". Nou te itilize de kòmandman - insert ak aktyalizasyon, kidonk egzakteman 500 tranzaksyon de kòmandman yo te toujou mete nan yon pakèt epi nou pa te fè eksperyans okenn pwoblèm. Apre yo fin ajoute dezyèm aktyalizasyon a, modifikasyon nou an sispann travay:

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;

Se konsa, pwochen travay la se asire w ke done ki soti nan tablo orijinal la, ki te chanje nan yon sèl tranzaksyon, fini nan nouvo tablo a tou nan yon sèl tranzaksyon.

Refize nan pakèt

Epi ankò nou te gen de solisyon. Premyèman: se pou nou konplètman abandone patisyon an pakèt epi transfere done nan yon sèl tranzaksyon. Avantaj nan solisyon sa a se senplisite li yo - chanjman kòd ki nesesè yo te minim (nan chemen an, nan ansyen vèsyon pg_reorg te travay egzakteman tankou sa). Men, gen yon pwoblèm - nou ap kreye yon tranzaksyon ki dire lontan, ak sa a, jan yo te di deja, se yon menas a Aparisyon nan yon nouvo gonfleman.

Dezyèm solisyon an pi konplèks, men pwobableman pi kòrèk: kreye yon kolòn nan tablo boutèy la ak idantifyan tranzaksyon an ki te ajoute done sou tab la. Lè sa a, lè nou kopye done, nou ka gwoup li pa atribi sa a epi asire ke chanjman ki gen rapò yo transfere ansanm. Pakèt la pral fòme nan plizyè tranzaksyon (oswa yon sèl gwo) ak gwosè li yo pral varye selon konbyen done yo te chanje nan tranzaksyon sa yo. Li enpòtan pou sonje ke depi done ki sòti nan tranzaksyon diferan antre nan tablo boutèy la nan yon lòd o aza, li p ap posib ankò li sekans, jan li te ye anvan an. seqscan pou chak demann ak filtraj pa tx_id twò chè, se yon endèks ki nesesè, men li pral tou ralanti metòd la akòz anlè a nan mete ajou li. An jeneral, kòm toujou, ou bezwen sakrifye yon bagay.

Se konsa, nou deside kòmanse ak premye opsyon a, kòm li se pi senp. Premyèman, li te nesesè yo konprann si yon tranzaksyon long ta dwe yon pwoblèm reyèl. Depi transfè prensipal la nan done ki soti nan ansyen tab la nan nouvo a tou rive nan yon tranzaksyon long, kesyon an transfòme nan "konbyen nou pral ogmante tranzaksyon sa a?" Dire premye tranzaksyon an depann sitou sou gwosè tab la. Dire yon nouvo depann de konbyen chanjman akimile nan tablo a pandan transfè done a, i.e. sou entansite chaj la. Kouri pg_repack la te fèt pandan yon tan nan chaj sèvis minimòm, ak volim chanjman yo te disproporsyonèlman ti konpare ak gwosè orijinal la nan tab la. Nou deside ke nou ta ka neglije tan an nan yon nouvo tranzaksyon (pou konparezon, an mwayèn li se 1 èdtan ak 2-3 minit).

Eksperyans yo te pozitif. Lanse sou pwodiksyon tou. Pou klè, isit la se yon foto ak gwosè youn nan baz done yo apre kouri:

Postgres: bloat, pg_repack ak kontrent difere

Depi nou te konplètman satisfè ak solisyon sa a, nou pa t eseye aplike dezyèm yon sèl la, men nou ap konsidere posiblite pou diskite sou li ak devlopè ekstansyon yo. Revizyon aktyèl nou an, malerezman, poko pare pou piblikasyon, paske nou sèlman rezoud pwoblèm nan ak restriksyon difere inik, epi pou yon patch konplè li nesesè bay sipò pou lòt kalite. Nou espere pou nou kapab fè sa alavni.

Petèt ou gen yon kesyon, poukisa nou menm te patisipe nan istwa sa a ak modifikasyon nan pg_repack, epi pa t ', pou egzanp, sèvi ak analogue li yo? Nan kèk pwen nou menm tou nou te panse sou sa a, men eksperyans nan pozitif nan sèvi ak li pi bonè, sou tab san kontrent difere, motive nou pou yo eseye konprann sans nan pwoblèm nan epi ranje li. Anplis de sa, lè l sèvi avèk lòt solisyon tou mande tan pou fè tès yo, se konsa nou deside ke nou ta premye eseye ranje pwoblèm nan nan li, epi si nou reyalize ke nou pa t 'kapab fè sa nan yon tan rezonab, Lè sa a, nou ta kòmanse gade analòg. .

Jwenn

Ki sa nou ka rekòmande dapre pwòp eksperyans nou:

  1. Siveye gonfleman ou. Ki baze sou done siveyans, ou ka konprann kouman autovacuum byen konfigirasyon.
  2. Ajiste AUTOVACUUM pou kenbe gonfleman nan yon nivo akseptab.
  3. Si gonfleman an toujou ap grandi epi ou pa ka simonte li lè l sèvi avèk zouti ki pa nan bwat la, ou pa bezwen pè sèvi ak ekstansyon ekstèn. Bagay pwensipal lan se teste tout bagay byen.
  4. Ou pa bezwen pè modifye solisyon ekstèn selon bezwen ou yo - pafwa sa ka pi efikas e menm pi fasil pase chanje pwòp kòd ou.

Sous: www.habr.com

Add nouvo kòmantè