Monitorings

VACUUM FULL vai pg_repack: kā samazināt uzpūstu PostgreSQL tabulu bez dīkstāves

Parasts VACUUM atbrīvo vietu atkārtotai izmantošanai, bet reti atdod to diskam. VACUUM FULL to dara, bet bloķē tabulu visā darbības laikā. pg_repack un PostgreSQL 19 jaunais REPACK (CONCURRENTLY) veic to pašu pārrakstīšanu tikai ar īsām slēdzenēm, un katram ir savi asie stūri.

· 15 min lasīšanai · AG Data komanda

VACUUM FULL vai pg_repack ir izvēle, ar ko saskaraties, kad PostgreSQL tabula izaugusi krietni lielāka par tajā esošajiem datiem un jums vajag atgūt diska vietu. Abi pārraksta tabulu kompaktā jaunā failā. VACUUM FULL ir iebūvēts, bet bloķē tabulu visā pārrakstīšanas laikā. pg_repack ir paplašinājums, kas dara to pašu, lielāko daļu laika atstājot tabulu pieejamu lasīšanai un rakstīšanai. Un PostgreSQL 19, kas pašlaik ir laidiena kandidāta stadijā, pievieno iebūvētu REPACK (CONCURRENTLY), kas strādā pēc tā paša principa.

Vispirms: vai pārrakstīšana tiešām vajadzīga?

VACUUM dokumentācija skaidri apraksta atšķirību. Parasts VACUUM atgūst vietu un padara to pieejamu atkārtotai izmantošanai tajā pašā tabulā bez ekskluzīvas slēdzenes, bet vairumā gadījumu neatdod to operētājsistēmai. Izņēmums, saskaņā ar nodaļu par regulāro vakuumēšanu, ir tad, kad lapas pašās tabulas beigās kļūst pilnīgi tukšas un ekskluzīvu slēdzeni var viegli iegūt: tad šīs lapas tiek nogrieztas.

Tātad tabula, kas ir 60% tukša, nav automātiski problēma. Ja tā atkal piepildīsies ar jaunām rindām, atkārtoti izmantojama vieta ir kārtībā. Tajā pašā nodaļā teikts, ka nav lielas jēgas saspiest tabulu, kas vienkārši atkal izaugs, un ka mēreni bieži standarta VACUUM ir labāki par retiem VACUUM FULL. Pārrakstīšana ir jēgpilna, ja:

Ja bloat atgriežas atkal un atkal, pārrakstīšana tikai nopērk laiku. Cēlonis gandrīz vienmēr ir autovacuum, kas netiek līdzi, vai gara transakcija, kas aiztur tīrīšanu; to aplūkojam autovacuum regulēšanas rakstā.

Izmēriet, pirms izlemjat

Sāciet ar izmēriem un mirušo rindu skaitu no statistikas skatiem:

SELECT relname,
       pg_size_pretty(pg_table_size(relid))   AS table_size,
       pg_size_pretty(pg_indexes_size(relid)) AS indexes_size,
       n_live_tup, n_dead_tup, last_autovacuum
FROM pg_stat_user_tables
ORDER BY pg_total_relation_size(relid) DESC
LIMIT 20;

n_dead_tup ir aplēse un neko nepasaka par brīvo vietu, ko atstājušas rindas, kuras vacuum jau iztīrījis. Reālam skaitlim izmantojiet paplašinājumu pgstattuple. pgstattuple_approx ir dokumentēta ātrāka pgstattuple alternatīva, kas atgriež aptuvenus rezultātus:

CREATE EXTENSION IF NOT EXISTS pgstattuple;

SELECT table_len, approx_tuple_percent, dead_tuple_percent, approx_free_percent
FROM pgstattuple_approx('public.orders'::regclass);

Augsts approx_free_percent lielai tabulai, kas vairs neaugs, ir jūsu kandidāts. Pēc noklusējuma šīs funkcijas var izpildīt tikai superlietotāji un pg_stat_scan_tables dalībnieki. Pat aptuvenā versija nolasa daļu tabulas, tāpēc ļoti lielām tabulām palaidiet to ārpus noslodzes stundām.

VACUUM FULL: vienkāršs, iebūvēts un bloķējošs

Saskaņā ar dokumentāciju VACUUM FULL pārraksta visu tabulas saturu jaunā diska failā bez liekas vietas, ļaujot neizmantoto vietu atdot operētājsistēmai. Cena:

VACUUM (FULL, VERBOSE, ANALYZE) public.orders;

-- citā sesijā
SELECT pid, command, phase, heap_blks_scanned, heap_blks_total
FROM pg_stat_progress_cluster;

Dokumentācijā norādīts, ka procesi, kas izpilda VACUUM FULL, ziņo par progresu skatā pg_stat_progress_cluster, nevis pg_stat_progress_vacuum. Starp citu, autovacuum nekad neizpilda VACUUM FULL.

VACUUM FULL ir pareizais rīks mazām tabulām, kur īsa slēdzene nav svarīga, apkopes logiem un gadījumiem, kad nevarat instalēt paplašinājumus. Visam lielam un noslogotam skatieties tiešsaistes variantus.

pg_repack: pārrakstīšana tiešsaistē

pg_repack ir atvērtā koda paplašinājums, kas novērš bloat tabulās un indeksos. Tā dokumentācijā norādīts atbalsts PostgreSQL 9.5 un jaunākām versijām, ieskaitot 18. Tas var veikt tiešsaistes CLUSTER (rindas sakārtotas pēc indeksa) vai ar --no-order tiešsaistes VACUUM FULL. Pilna tabulas pārpakošana notiek tā:

  1. Izveido žurnāla tabulu un trigeri, kas ieraksta katru INSERT, UPDATE un DELETE sākotnējā tabulā.
  2. Izveido jaunu tabulu ar visām vecās tabulas rindām un uzbūvē tās indeksus.
  3. Piemēro žurnāla tabulā uzkrātās izmaiņas.
  4. Sistēmas katalogos apmaina tabulas, ieskaitot indeksus un TOAST, un dzēš sākotnējo.

ACCESS EXCLUSIVE slēdzene tiek turēta tikai īsu brīdi sagatavošanas laikā un beigu apmaiņas un dzēšanas laikā. Pārējā laikā pg_repack tur SHARE UPDATE EXCLUSIVE slēdzeni (kopš versijas 1.5.3; agrākās versijas izmantoja ACCESS SHARE), tāpēc parasta lasīšana un rakstīšana turpinās.

-- vienreiz katrā datubāzē
CREATE EXTENSION pg_repack;

# apskatīt, kas tiktu apstrādāts, neko nedarot
pg_repack --dry-run --no-order --table=public.orders mydb

# tiešsaistes "VACUUM FULL" vienai tabulai; padoties, nevis atcelt citus vaicājumus
pg_repack --no-order --table=public.orders --wait-timeout=30 --no-kill-backend mydb

Kas pg_repack vajadzīgs

Kur tas var sāpēt

Ja uzpūsti ir tikai indeksi, tabulas pārrakstīšana nemaz nav vajadzīga. pg_repack ir --only-indexes, un kopš PostgreSQL 12 iebūvētais REINDEX CONCURRENTLY to paveic bez paplašinājuma.

PostgreSQL 19: REPACK un REPACK (CONCURRENTLY)

PostgreSQL 19 laidiena piezīmes pievieno komandu REPACK, kas aizstāj VACUUM FULL un CLUSTER; vecās komandas saglabātas saderībai, un PostgreSQL 19 VACUUM lapā opcija FULL atzīmēta kā novecojusi. Vēl svarīgāk, REPACK (CONCURRENTLY) pārbūvē tabulu, neturot access-exclusive slēdzeni visas operācijas laikā. Šodien PostgreSQL 19 ir laidiena kandidāta stadijā (RC1 tika izziņots 2026. gada 15. oktobrī), tāpēc uztveriet to kā to, kas nāks, nevis to, ko darbināt tagad.

-- PostgreSQL 19
REPACK (CONCURRENTLY, VERBOSE, ANALYZE) public.orders;

SELECT * FROM pg_stat_progress_repack;

Saskaņā ar REPACK dokumentāciju vienlaicīgais režīms lielāko darba daļu veic ar SHARE UPDATE EXCLUSIVE, vienlaicīgās izmaiņas uztver ar loģisko dekodēšanu un ACCESS EXCLUSIVE ņem tikai beigu apmaiņai. Dokumentētos ierobežojumus vērts izlasīt, pirms to plānojat:

Neatkarīgi no izvēlētā rīka vispirms pārbaudiet disku. Katrs no šiem variantiem uzraksta pilnu jaunu tabulas un tās indeksu kopiju, pirms vecā tiek dzēsta. Ja vietu atgūstat tāpēc, ka disks ir gandrīz pilns, vispirms atbrīvojiet vietu citur, citādi pati pārrakstīšana kļūs par avāriju. Ārkārtas soļi aprakstīti mūsu rakstā par pilnu disku.

Ko izmantot

Galvenās atziņas

PostgreSQL Bloat VACUUM pg_repack
Sadarbība ar mums

Tabulas lielākas par to datiem?

Mēs izmērām bloat, tiešsaistē pārrakstām tabulas, kurām tas vajadzīgs, un salabojam vacuum iestatījumus un garās transakcijas, kas to izraisīja.

Sazināties Vairāk no emuāra