Postgres: kembung, pg_repack lan watesan sing ditundha

Postgres: kembung, pg_repack lan watesan sing ditundha

Efek bloat ing tabel lan indeks umume dikenal lan ora mung ana ing Postgres. Ana cara kanggo ngatasi metu saka kothak, kaya VACUUM FULL utawa CLUSTER, nanging padha ngunci tabel sajrone operasi lan mulane ora bisa digunakake.

Artikel kasebut bakal ngemot teori sethithik babagan carane kembung, carane sampeyan bisa nglawan, babagan kendala sing ditundha lan masalah sing digawa menyang panggunaan ekstensi pg_repack.

Artikel iki ditulis adhedhasar pituturku ing PgConf.Russia 2020.

Kenapa kembung kedadeyan?

Postgres adhedhasar model multi-versi (MVCC). Intine yaiku saben baris ing tabel bisa duwe sawetara versi, nalika transaksi ndeleng ora luwih saka siji versi iki, nanging ora kudu padha. Iki ngidini sawetara transaksi bisa bebarengan lan meh ora ana impact ing saben liyane.

Temenan, kabeh versi kasebut kudu disimpen. Postgres dianggo karo kaca memori saben kaca lan kaca minangka jumlah data minimal sing bisa diwaca saka disk utawa ditulis. Ayo goleki conto cilik kanggo ngerti kepiye kedadeyan kasebut.

Ayo kita duwe tabel sing wis ditambahake sawetara cathetan. Data anyar wis katon ing kaca pisanan file ing ngendi tabel disimpen. Iki versi urip baris sing kasedhiya kanggo transaksi liyane sawise commit (kanggo gamblang, kita bakal nganggep yen tingkat isolasi Read Committed).

Postgres: kembung, pg_repack lan watesan sing ditundha

Kita banjur nganyari salah siji entri, saéngga menehi tandha versi lawas minangka ora cocog maneh.

Postgres: kembung, pg_repack lan watesan sing ditundha

Langkah demi langkah, nganyari lan mbusak versi baris, kita rampung karo kaca sing kira-kira setengah saka data minangka "sampah". Data iki ora katon kanggo transaksi apa wae.

Postgres: kembung, pg_repack lan watesan sing ditundha

Postgres duwe mekanisme VACUUM, sing ngresiki versi lungse lan ndadekake papan kanggo data anyar. Nanging yen ora dikonfigurasi kanthi agresif utawa sibuk nggarap tabel liyane, banjur "data sampah" tetep, lan kita kudu nggunakake kaca tambahan kanggo data anyar.

Dadi ing conto kita, ing sawetara wektu tabel bakal kalebu papat kaca, nanging mung setengah saka iku bakal ngemot data langsung. Akibaté, nalika ngakses tabel, kita bakal maca data luwih akeh tinimbang sing dibutuhake.

Postgres: kembung, pg_repack lan watesan sing ditundha

Sanajan VACUUM saiki mbusak kabeh versi baris sing ora relevan, kahanan kasebut ora bakal saya apik. Kita bakal duwe ruang kosong ing kaca utawa malah kabeh kaca kanggo baris anyar, nanging kita isih bakal maca data luwih akeh tinimbang sing dibutuhake.
Miturut cara, yen kaca kosong (sing nomer loro ing conto kita) ana ing mburi file, banjur VACUUM bakal bisa motong. Nanging saiki dheweke ana ing tengah, mula ora ana sing bisa ditindakake.

Postgres: kembung, pg_repack lan watesan sing ditundha

Nalika jumlah kaca kosong utawa arang banget dadi gedhe, sing diarani bloat, mula mengaruhi kinerja.

Kabeh sing diterangake ing ndhuwur minangka mekanisme kedadeyan bloat ing tabel. Ing indeks iki kedadeyan kanthi cara sing padha.

Apa aku duwe kembung?

Ana sawetara cara kanggo nemtokake yen sampeyan duwe kembung. Ide pisanan yaiku nggunakake statistik Postgres internal, sing ngemot informasi kira-kira babagan jumlah larik ing tabel, jumlah larik "urip", lan liya-liyane. Sampeyan bisa nemokake akeh variasi skrip sing wis siap ing Internet. We njupuk minangka basis naskah saka PostgreSQL Experts, sing bisa ngevaluasi tabel bloat bebarengan karo roti panggang lan indeks btree bloat. Ing pengalaman kita, kesalahane yaiku 10-20%.

Cara liya yaiku nggunakake ekstensi pgstattuple, sing ngidini sampeyan ndeleng ing jero kaca lan entuk perkiraan lan nilai bloat sing tepat. Nanging ing kasus kapindho, sampeyan kudu mindhai kabeh tabel.

Kita nganggep nilai bloat cilik, nganti 20%, bisa ditampa. Bisa dianggep minangka analog saka fillfactor kanggo tabel и indeks. Ing 50% lan ndhuwur, masalah kinerja bisa diwiwiti.

Cara kanggo nglawan kembung

Postgres duwe sawetara cara kanggo ngatasi bloat metu saka kothak, nanging ora mesthi cocok kanggo kabeh wong.

Konfigurasi AUTOVACUUM supaya ora kembung. Utawa luwih tepate, supaya ing tingkat ditrima kanggo sampeyan. Iki misale jek kaya saran "kapten", nanging ing kasunyatan iki ora tansah gampang kanggo entuk. Contone, sampeyan duwe pangembangan aktif kanthi owah-owahan biasa ing skema data, utawa sawetara jinis migrasi data lagi ditindakake. Akibaté, profil beban sampeyan bisa uga kerep diganti lan biasane beda-beda saka tabel menyang tabel. Iki tegese sampeyan kudu terus-terusan kerja rada maju lan nyetel AUTOVACUUM menyang profil ganti saben meja. Nanging temenan iki ora gampang ditindakake.

Alasan umum liyane kenapa AUTOVACUUM ora bisa ngetutake tabel amarga ana transaksi sing wis suwe ora bisa ngresiki data sing kasedhiya kanggo transaksi kasebut. Rekomendasi ing kene uga jelas - nyingkirake transaksi "dangling" lan nyilikake wektu transaksi aktif. Nanging yen beban ing aplikasi sampeyan minangka hibrida saka OLAP lan OLTP, mula sampeyan bisa uga duwe pirang-pirang nganyari lan pitakon singkat, uga operasi jangka panjang - contone, nggawe laporan. Ing kahanan kaya mengkono, iku worth mikir bab nyebarake beban ing basis beda, kang bakal ngidini saben liyane fine-tuning.

Conto liyane - sanajan profil kasebut homogen, nanging database ana ing beban sing dhuwur banget, mula AUTOVACUUM sing paling agresif ora bisa ngatasi, lan kembung bakal kedadeyan. Scaling (vertikal utawa horisontal) mung solusi.

Apa apa ing kahanan sing wis nyiyapake AUTOVACUUM, nanging bloat terus kanggo tuwuh.

tim VACUUM FULL mbangun maneh isi tabel lan indeks lan mung ninggalake data sing cocog. Kanggo ngilangke bloat, kerjane sampurna, nanging sak eksekusi sawijining kunci eksklusif ing meja dijupuk (AccessExclusiveLock), kang ora bakal ngidini ngukum pitakonan ing meja iki, malah milih. Yen sampeyan bisa mungkasi layanan utawa bagean saka sawetara wektu (saka puluhan menit nganti sawetara jam gumantung saka ukuran database lan hardware), banjur pilihan iki paling apik. Sayange, kita ora duwe wektu kanggo mbukak VACUUM FULL sak pangopènan dijadwal, supaya cara iki ora cocok kanggo kita.

tim KLUSTER Mbangun maneh isi tabel kanthi cara sing padha karo VACUUM FULL, nanging ngidini sampeyan nemtokake indeks miturut data sing bakal diurutake kanthi fisik ing disk (nanging ing mangsa ngarep urutan kasebut ora dijamin kanggo baris anyar). Ing kahanan tartamtu, iki minangka optimasi sing apik kanggo sawetara pitakon - kanthi maca sawetara cathetan kanthi indeks. Kerugian perintah kasebut padha karo VACUUM FULL - ngunci meja sajrone operasi.

tim REINDEX padha karo loro sadurunge, nanging mbangun maneh indeks tartamtu utawa kabeh indeks meja. Kunci rada lemah: ShareLock ing meja (nyegah modifikasi, nanging ngidini pilih) lan AccessExclusiveLock ing indeks sing dibangun maneh (pamblokiran pitakon nggunakake indeks iki). Nanging, ing versi 12 saka Postgres parameter muncul SAMPEYAN, sing ngidini sampeyan mbangun maneh indeks tanpa ngalangi tambahan, modifikasi, utawa mbusak rekaman bebarengan.

Ing versi Postgres sadurungé, sampeyan bisa entuk asil sing padha karo REINDEX SAMPINGAN nggunakake Nggawe indeks bebarengan. Ngidini sampeyan nggawe indeks tanpa ngunci sing ketat (ShareUpdateExclusiveLock, sing ora ngganggu pitakon paralel), banjur ngganti indeks lawas karo sing anyar lan mbusak indeks lawas. Iki ngidini sampeyan ngilangi kembung indeks tanpa ngganggu aplikasi sampeyan. Penting kanggo nimbang yen nalika mbangun indeks bakal ana beban tambahan ing subsistem disk.

Mangkono, yen kanggo indeks ana cara kanggo ngilangi kembung "ing fly", banjur ora ana kanggo tabel. Ing kene ana macem-macem ekstensi eksternal: pg_repack (biyen pg_reorg), pgkompak, pgcompacttable lan liya-liyane. Ing artikel iki, aku ora bakal mbandhingake lan mung bakal ngomong babagan pg_repack, sing, sawise sawetara modifikasi, kita nggunakake awake dhewe.

Cara kerja pg_repack

Postgres: kembung, pg_repack lan watesan sing ditundha
Ayo kita duwe tabel sing biasa - kanthi indeks, watesan lan, sayangé, kanthi kembung. Langkah pisanan pg_repack yaiku nggawe tabel log kanggo nyimpen data babagan kabeh owah-owahan nalika lagi mlaku. Pemicu bakal niru owah-owahan iki kanggo saben sisipan, nganyari lan mbusak. Banjur tabel digawe, padha karo sing asli ing struktur, nanging tanpa indeks lan watesan, supaya ora alon proses nglebokake data.

Sabanjure, pg_repack nransfer data saka tabel lawas menyang tabel anyar, kanthi otomatis nyaring kabeh baris sing ora cocog, banjur nggawe indeks kanggo tabel anyar. Sajrone eksekusi kabeh operasi kasebut, owah-owahan akumulasi ing tabel log.

Langkah sabanjure yaiku nransfer owah-owahan menyang tabel anyar. Migrasi dileksanakake liwat sawetara iterasi, lan nalika ana kurang saka 20 entri kiwa ing meja log, pg_repack ndarbeni kunci kuwat, migrasi data paling anyar, lan ngganti tabel lawas karo anyar ing Tabel sistem Postgres. Iki mung lan wektu cendhak banget nalika sampeyan ora bakal bisa kanggo bisa karo meja. Sawise iki, tabel lawas lan tabel kanthi log bakal dibusak lan spasi dibebasake ing sistem file. Proses rampung.

Kabeh katon apik ing teori, nanging apa sing kedadeyan ing praktik? Kita nyoba pg_repack tanpa beban lan ing beban, lan mriksa operasi kasebut yen mandheg prematur (kanthi tembung liya, nggunakake Ctrl + C). Kabeh tes positif.

Kita menyang toko panganan - banjur kabeh ora kaya sing dikarepake.

Pancake pisanan didol

Ing kluster pisanan, kita nampa kesalahan babagan nglanggar kendala unik:

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

Watesan iki nduweni jeneng index_16508 kanthi otomatis - digawe dening pg_repack. Adhedhasar atribut sing kalebu ing komposisi kasebut, kita nemtokake kendala "kita" sing cocog karo iku. Masalahe ternyata iki dudu watesan sing biasa, nanging sing ditundha (kendala sing ditundha), i.e. verifikasi dileksanakake mengko saka printah sql, kang ndadékaké kanggo jalaran sing ora dikarepke.

Watesan sing ditundha: kenapa dibutuhake lan cara kerjane

A teori sethitik babagan Watesan ditanggepi.
Ayo nimbang conto sing prasaja: kita duwe buku referensi tabel mobil kanthi rong atribut - jeneng lan urutan mobil ing direktori.
Postgres: kembung, pg_repack lan watesan sing ditundha

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



Ayo kita ngomong yen kita kudu ngganti mobil pisanan lan kaloro. Solusi langsung yaiku nganyari nilai pertama menyang nomer loro, lan nomer loro dadi nomer siji:

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

Nanging nalika kita mbukak kode iki, kita ngarepake pelanggaran kendala amarga urutan nilai ing tabel unik:

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

Carane aku bisa nindakake iku beda? Pilihan siji: nambah panggantos nilai tambahan kanggo pesenan sing dijamin ora ana ing meja, contone "-1". Ing pemrograman, iki diarani "ijol-ijolan nilai saka rong variabel liwat katelu." Mung drawback saka cara iki nganyari tambahan.

Opsi loro: Ngrancang ulang tabel kanggo nggunakake jinis data titik ngambang kanggo nilai pesenan tinimbang integer. Banjur, nalika nganyari nilai saka 1, contone, kanggo 2.5, entri pisanan bakal kanthi otomatis "ngadeg" antarane kaloro lan katelu. Solusi iki bisa digunakake, nanging ana rong watesan. Kaping pisanan, ora bakal bisa digunakake yen nilai kasebut digunakake ing endi wae ing antarmuka. Kapindho, gumantung saka presisi jinis data, sampeyan bakal duwe sawetara sisipan sing bisa ditindakake sadurunge ngetung maneh nilai kabeh cathetan.

Opsi telu: gawe kendala ditundha supaya dicenthang mung nalika nindakake:

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

Amarga logika panyuwunan awal kita mesthekake yen kabeh nilai unik nalika komitmen, mula bakal sukses.

Conto sing dibahas ing ndhuwur, mesthi, banget sintetik, nanging nuduhake ide kasebut. Ing aplikasi kita, kita nggunakake kendala sing ditundha kanggo ngleksanakake logika sing tanggung jawab kanggo ngrampungake konflik nalika pangguna bebarengan nggarap obyek widget sing dienggo bareng ing papan. Nggunakake watesan kasebut ngidini kita nggawe kode aplikasi luwih gampang.

Umumé, gumantung saka jinis kendala, Postgres duwe telung tingkat granularitas kanggo mriksa: tingkat baris, transaksi, lan ekspresi.
Postgres: kembung, pg_repack lan watesan sing ditundha
Source: begriffs

CHECK lan NOT NULL tansah dicenthang ing tingkat baris; kanggo watesan liyane, kaya sing bisa dideleng saka tabel, ana pilihan sing beda. Sampeyan bisa maca liyane kene.

Kanggo ngringkes kanthi ringkes, watesan sing ditundha ing sawetara kahanan nyedhiyakake kode sing luwih bisa diwaca lan luwih sithik prentah. Nanging, sampeyan kudu mbayar iki dening complicating proses debugging, wiwit wayahe kesalahan occurs lan wayahe sampeyan mangerteni bab iku dipisahake ing wektu. Masalah liyane sing bisa ditindakake yaiku manawa panjadwal ora bisa nggawe rencana sing optimal yen panyuwunan kasebut kalebu watesan sing ditundha.

Peningkatan pg_repack

Kita wis nutupi apa watesan sing ditundha, nanging kepiye hubungane karo masalah kita? Ayo elinga kesalahan sing ditampa sadurunge:

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

Iki kedadeyan nalika data disalin saka tabel log menyang tabel anyar. Iki katon aneh amarga ... data ing tabel log wis setya bebarengan karo data ing tabel sumber. Yen padha gawe marem alangan saka Tabel asli, carane padha bisa nerak alangan padha ing anyar?

Dadi metu, ROOT saka masalah dumunung ing langkah sadurungé saka pg_repack, kang nggawe mung indeks, nanging ora alangan: Tabel lawas wis kendala unik, lan anyar digawe indeks unik tinimbang.

Postgres: kembung, pg_repack lan watesan sing ditundha

Wigati dicathet ing kene yen kendala kasebut normal lan ora ditundha, mula indeks unik sing digawe malah padha karo kendala iki, amarga Watesan unik ing Postgres ditindakake kanthi nggawe indeks unik. Nanging ing kasus kendala sing ditundha, prilaku kasebut ora padha, amarga indeks kasebut ora bisa ditundha lan tansah dicenthang nalika perintah sql dieksekusi.

Mangkono, inti saka masalah kasebut dumunung ing "tundha" mriksa: ing tabel asli kedadeyan nalika komit, lan ing tabel anyar nalika perintah sql dieksekusi. Iki tegese kita kudu mesthekake yen mriksa dileksanakake padha ing loro kasus: salah siji tansah telat, utawa tansah langsung.

Dadi, ide apa sing kita duwe?

Nggawe indeks sing padha karo sing ditundha

Ide pisanan kanggo nindakake loro mriksa ing mode langsung. Iki bisa ngasilake sawetara watesan positif palsu, nanging yen ana sawetara, iki ora bakal mengaruhi karya pangguna, amarga konflik kasebut minangka kahanan normal kanggo wong-wong mau. Iki kedadeyan, contone, nalika pangguna loro miwiti nyunting widget sing padha ing wektu sing padha, lan klien pangguna kaping pindho ora duwe wektu kanggo nampa informasi manawa widget kasebut wis diblokir kanggo diowahi dening pangguna pisanan. Ing kahanan kaya mengkono, server nolak pangguna kapindho, lan klien nggulung maneh owah-owahan lan mblokir widget. Ora suwe, nalika pangguna pisanan ngrampungake panyuntingan, sing nomer loro bakal nampa informasi manawa widget ora diblokir maneh lan bakal bisa mbaleni tumindake.

Postgres: kembung, pg_repack lan watesan sing ditundha

Kanggo mesthekake yen mriksa tansah ing mode non-ditundha, kita nggawe indeks anyar padha karo watesan tundha asli:

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

Ing lingkungan test, kita nampa mung sawetara kasalahan samesthine. Sukses! We mlayu pg_repack maneh ing produksi lan entuk 5 kasalahan ing kluster pisanan ing jam karya. Iki minangka asil sing bisa ditampa. Nanging, wis ana ing kluster kapindho, jumlah kesalahan saya tambah akeh lan kudu mandheg pg_repack.

Yagene kedadeyan kasebut? Kemungkinan ana kesalahan gumantung saka jumlah pangguna sing nggarap widget sing padha ing wektu sing padha. Ketoke, ing wayahe ana owah-owahan competitive akeh kurang karo data sing disimpen ing kluster pisanan saka liyane, i.e. kita padha mung "bejo".

Ide iki ora bisa. Ing wektu iku, kita weruh loro solusi liyane: nulis ulang kode aplikasi kita kanggo dispense karo kendala tundha, utawa "ngajari" pg_repack kanggo bisa karo wong-wong mau. Kita milih sing nomer loro.

Ganti indeks ing tabel anyar kanthi watesan sing ditundha saka tabel asli

Tujuan revisi kasebut jelas - yen tabel asli duwe kendala sing ditundha, mula kanggo sing anyar sampeyan kudu nggawe kendala kasebut, lan dudu indeks.

Kanggo nguji owah-owahan, kita nulis tes prasaja:

  • Tabel kanthi watesan sing ditundha lan siji rekaman;
  • nglebokake data ing daur ulang sing bertentangan karo rekaman sing ana;
  • nindakake nganyari - data ora konflik maneh;
  • nindakake owah-owahan.

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;

Versi asli pg_repack tansah tabrakan ing sisipan pisanan, versi sing diowahi bisa digunakake tanpa kasalahan. gedhe.

Kita pindhah menyang produksi lan maneh entuk kesalahan ing fase sing padha kanggo nyalin data saka tabel log menyang sing anyar:

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

Kahanan klasik: kabeh bisa digunakake ing lingkungan tes, nanging ora ing produksi?!

APPLY_COUNT lan persimpangan rong kumpulan

Kita wiwit nganalisa kode kasebut kanthi harfiah saben baris lan nemokake titik penting: data ditransfer saka tabel log menyang sing anyar kanthi batch, konstanta APPLY_COUNT nuduhake ukuran batch:

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

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

Masalahe yaiku data saka transaksi asli, ing ngendi sawetara operasi bisa nglanggar kendala, nalika ditransfer, bisa rampung ing persimpangan rong kumpulan - setengah saka prentah bakal ditindakake ing batch pisanan, lan setengah liyane. ing kaloro. Lan ing kene, gumantung nasib sampeyan: yen tim ora nglanggar apa-apa ing batch pisanan, mula kabeh apik, nanging yen nindakake, ana kesalahan.

APPLY_COUNT padha karo 1000 cathetan, sing nerangake kenapa tes kita sukses - ora kalebu kasus "persimpangan kumpulan". Kita nggunakake rong printah - masang lan nganyari, supaya persis 500 transaksi saka loro printah tansah diselehake ing batch lan kita ora nemu masalah. Sawise nambahake nganyari kapindho, suntingan kita mandheg:

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;

Dadi, tugas sabanjure yaiku kanggo mesthekake yen data saka tabel asli, sing diganti ing siji transaksi, bakal ana ing tabel anyar uga ing siji transaksi.

Nolak saka batching

Lan maneh kita duwe rong solusi. Pisanan: ayo ninggalake pemisahan dadi batch lan transfer data ing siji transaksi. Kauntungan saka solusi iki yaiku kesederhanaan - owah-owahan kode sing dibutuhake minimal (kanthi cara, ing versi lawas pg_reorg kerjane kaya ngono). Nanging ana masalah - kita nggawe transaksi long-mlaku, lan iki, minangka sadurunge ngandika, ancaman kanggo emergence saka bloat anyar.

Solusi kapindho luwih rumit, nanging bisa uga luwih bener: nggawe kolom ing tabel log kanthi pengenal transaksi sing nambahake data ing meja. Banjur, nalika kita nyalin data, kita bisa klompok miturut atribut iki lan mesthekake yen owah-owahan sing gegandhengan ditransfer bebarengan. Kumpulan kasebut bakal dibentuk saka sawetara transaksi (utawa siji sing gedhe) lan ukurane bakal beda-beda gumantung saka jumlah data sing diganti ing transaksi kasebut. Wigati dimangerteni manawa data saka transaksi sing beda-beda mlebu ing tabel log kanthi urutan acak, mula ora bisa maca kanthi urutan, kaya sadurunge. seqscan kanggo saben request karo nyaring dening tx_id larang banget, indeks dibutuhake, nanging uga bakal alon mudhun cara amarga nduwur sirah nganyari iku. Umumé, minangka tansah, sampeyan kudu kurban soko.

Dadi, kita mutusake kanggo miwiti kanthi pilihan pisanan, amarga luwih gampang. Kaping pisanan, sampeyan kudu ngerti apa transaksi sing dawa bakal dadi masalah nyata. Wiwit transfer data utama saka tabel lawas menyang sing anyar uga ana ing siji transaksi sing dawa, pitakonan kasebut diowahi dadi "sepira kita bakal nambah transaksi iki?" Duration saka transaksi pisanan gumantung utamané ing ukuran meja. Duration saka anyar gumantung carane akeh owah-owahan nglumpukake ing tabel sak transfer data, i.e. ing intensitas beban. Run pg_repack kedaden sak wektu mbukak layanan minimal, lan volume owah-owahan ana disproportionately cilik dibandhingake ukuran asli saka meja. Kita mutusake yen kita bisa nglirwakake wektu transaksi anyar (kanggo mbandhingake, rata-rata yaiku 1 jam lan 2-3 menit).

Eksperimen kasebut positif. Bukak ing produksi uga. Kanggo gamblang, iki gambar kanthi ukuran salah sawijining database sawise mlaku:

Postgres: kembung, pg_repack lan watesan sing ditundha

Amarga kita wis rampung wareg karo solusi iki, kita ora nyoba kanggo ngleksanakake kaloro, nanging kita nimbang kamungkinan kanggo ngrembug karo pangembang extension. Revisi saiki, sayangé, durung siyap kanggo publikasi, amarga kita mung ngrampungake masalah kasebut kanthi watesan sing ditundha sing unik, lan kanggo tembelan lengkap kudu menehi dhukungan kanggo jinis liyane. Kita ngarep-arep bisa nindakake iki ing mangsa ngarep.

Sampeyan bisa uga duwe pitakonan, kenapa kita malah melu crita iki kanthi modifikasi pg_repack, lan ora, contone, nggunakake analoge? Ing sawetara titik, kita uga mikir babagan iki, nanging pengalaman positif nggunakake sadurunge, ing tabel tanpa alangan sing ditundha, menehi motivasi kanggo nyoba ngerteni inti masalah kasebut lan ndandani. Kajaba iku, nggunakake solusi liyane uga mbutuhake wektu kanggo nganakake tes, mula kita mutusake manawa bakal nyoba ndandani masalah kasebut, lan yen kita ngerti manawa ora bisa nindakake iki ing wektu sing cukup, mula kita bakal miwiti ndeleng analog. .

temonan

Apa sing bisa disaranake adhedhasar pengalaman dhewe:

  1. Ngawasi kembung sampeyan. Adhedhasar data ngawasi, sampeyan bisa ngerti carane autovacuum dikonfigurasi.
  2. Nyetel AUTOVACUUM supaya bloat ing tingkat ditrima.
  3. Yen kembung isih akeh lan sampeyan ora bisa ngatasi kanthi nggunakake alat sing ora ana ing kothak, aja wedi nggunakake ekstensi eksternal. Sing utama yaiku nyoba kabeh kanthi apik.
  4. Aja wedi ngowahi solusi eksternal sing cocog karo kabutuhan sampeyan - kadhangkala iki bisa dadi luwih efektif lan malah luwih gampang tinimbang ngganti kode sampeyan dhewe.

Source: www.habr.com

Add a comment