เชœเซเชฏเชพเชฐเซ‡ VACUUM เชจเชฟเชทเซเชซเชณ เชœเชพเชฏ เช›เซ‡, เชคเซเชฏเชพเชฐเซ‡ เช…เชฎเซ‡ เชŸเซ‡เชฌเชฒเชจเซ‡ เชฎเซ‡เชจเซเชฏเซเช…เชฒเซ€ เชธเชพเชซ เช•เชฐเซ€เช เช›เซ€เช

เชตเชพเชฏเซเชฎเซเชฏเซเชฎ PostgreSQL เชฎเชพเช‚ เช•เซ‹เชทเซเชŸเช•เชฎเชพเช‚เชฅเซ€ "เชธเชพเชซ" เช•เชฐเซ€ เชถเช•เซ‡ เช›เซ‡ เชฎเชพเชคเซเชฐ เชถเซเช‚ เช•เซ‹เชˆ เชœเซ‹เชˆ เชถเช•เชคเซเช‚ เชจเชฅเซ€ - เชเชŸเชฒเซ‡ เช•เซ‡, เช† เชฐเซ‡เช•เซ‹เชฐเซเชกเซเชธ เชฌเชฆเชฒเชพเชฏเชพ เชชเชนเซ‡เชฒเชพ เชถเชฐเซ‚ เชฅเชฏเซ‡เชฒเซ€ เชเช• เชชเชฃ เชธเช•เซเชฐเชฟเชฏ เชตเชฟเชจเช‚เชคเซ€ เชจเชฅเซ€.

เชชเชฐเช‚เชคเซ เชœเซ‹ เช†เชตเชพ เช…เชชเซเชฐเชฟเชฏ เชชเซเชฐเช•เชพเชฐ (OLTP เชกเซ‡เชŸเชพเชฌเซ‡เช เชชเชฐ เชฒเชพเช‚เชฌเชพ เช—เชพเชณเชพเชจเชพ OLAP เชฒเซ‹เชก) เชนเชœเซ เชชเชฃ เช…เชธเซเชคเชฟเชคเซเชตเชฎเชพเช‚ เชนเซ‹เชฏ เชคเซ‹ เชถเซเช‚? เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชธเช•เซเชฐเชฟเชฏ เชฐเซ€เชคเซ‡ เชฌเชฆเชฒเชพเชคเชพ เชŸเซ‡เชฌเชฒเชจเซ‡ เชธเชพเชซ เช•เชฐเซ‹ เชฒเชพเช‚เชฌเชพ เชชเซเชฐเชถเซเชจเซ‹เชฅเซ€ เช˜เซ‡เชฐเชพเชฏเซ‡เชฒเชพ เช…เชจเซ‡ เชฐเซ‡เช• เชชเชฐ เชชเช— เชฎเซ‚เช•เชคเชพ เชจเชฅเซ€?

เชœเซเชฏเชพเชฐเซ‡ VACUUM เชจเชฟเชทเซเชซเชณ เชœเชพเชฏ เช›เซ‡, เชคเซเชฏเชพเชฐเซ‡ เช…เชฎเซ‡ เชŸเซ‡เชฌเชฒเชจเซ‡ เชฎเซ‡เชจเซเชฏเซเช…เชฒเซ€ เชธเชพเชซ เช•เชฐเซ€เช เช›เซ€เช

เชฐเซ‡เช• เช…เชจเชซเซ‹เชฒเซเชกเชฟเช‚เช—

เชชเซเชฐเชฅเชฎ, เชšเชพเชฒเซ‹ เชจเช•เซเช•เซ€ เช•เชฐเซ€เช เช•เซ‡ เช†เชชเชฃเซ‡ เชœเซ‡ เชธเชฎเชธเซเชฏเชพ เชนเชฒ เช•เชฐเชตเชพ เชฎเชพเช‚เช—เซ€เช เช›เซ€เช เชคเซ‡ เชถเซเช‚ เช›เซ‡ เช…เชจเซ‡ เชคเซ‡ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชŠเชญเซ€ เชฅเชˆ เชถเช•เซ‡ เช›เซ‡.

เชธเชพเชฎเชพเชจเซเชฏ เชฐเซ€เชคเซ‡ เช† เชชเชฐเชฟเชธเซเชฅเชฟเชคเชฟ เชฅเชพเชฏ เช›เซ‡ เชชเซเชฐเชฎเชพเชฃเชฎเชพเช‚ เชจเชพเชจเชพ เชŸเซ‡เชฌเชฒ เชชเชฐ, เชชเชฐเช‚เชคเซ เชœเซ‡เชฎเชพเช‚ เชคเซ‡ เชฅเชพเชฏ เช›เซ‡ เช˜เชฃเชพ เชฌเชงเชพ เชซเซ‡เชฐเชซเชพเชฐเซ‹. เชธเชพเชฎเชพเชจเซเชฏ เชฐเซ€เชคเซ‡ เช† เช…เชฅเชตเชพ เช…เชฒเช— เชฎเซ€เชŸเชฐ/เชเช—เซเชฐเชฟเช—เซ‡เชŸเซเชธ/เชฐเซ‡เชŸเชฟเช‚เช—เซเชธ, เชœเซ‡เชจเชพ เชชเชฐ เช…เชชเชกเซ‡เชŸ เชตเชพเชฐเช‚เชตเชพเชฐ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡, เช…เชฅเชตเชพ เชฌเชซเชฐ-เช•เชคเชพเชฐ เช˜เชŸเชจเชพเช“เชจเชพ เชธเชคเชค เชšเชพเชฒเซ เชธเซเชŸเซเชฐเซ€เชฎ เชชเชฐ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡, เชœเซ‡เชจเชพ เชฐเซ‡เช•เซ‹เชฐเซเชกเซเชธ เชธเชคเชค INSERT/DELETE เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡.

เชšเชพเชฒเซ‹ เชฐเซ‡เชŸเชฟเช‚เช— เชธเชพเชฅเซ‡ เชตเชฟเช•เชฒเซเชชเชจเซ‡ เชชเซเชจเชƒเช‰เชคเซเชชเชพเชฆเชฟเชค เช•เชฐเชตเชพเชจเซ‹ เชชเซเชฐเชฏเชพเชธ เช•เชฐเซ€เช:

CREATE TABLE tbl(k text PRIMARY KEY, v integer);
CREATE INDEX ON tbl(v DESC); -- ะฟะพ ัั‚ะพะผัƒ ะธะฝะดะตะบััƒ ะฑัƒะดะตะผ ัั‚ั€ะพะธั‚ัŒ ั€ะตะนั‚ะธะฝะณ

INSERT INTO
  tbl
SELECT
  chr(ascii('a'::text) + i) k
, 0 v
FROM
  generate_series(0, 25) i;

เช…เชจเซ‡ เชธเชฎเชพเช‚เชคเชฐ, เช…เชจเซเชฏ เชœเซ‹เชกเชพเชฃเชฎเชพเช‚, เชเช• เชฒเชพเช‚เชฌเซ€, เชฒเชพเช‚เชฌเซ€ เชตเชฟเชจเช‚เชคเซ€ เชถเชฐเซ‚ เชฅเชพเชฏ เช›เซ‡, เช•เซ‡เชŸเชฒเชพเช• เชœเชŸเชฟเชฒ เช†เช‚เช•เชกเชพ เชเช•เชคเซเชฐเชฟเชค เช•เชฐเซ‡ เช›เซ‡, เชชเชฐเช‚เชคเซ เช…เชฎเชพเชฐเชพ เชŸเซ‡เชฌเชฒเชจเซ‡ เช…เชธเชฐ เช•เชฐเชคเซเช‚ เชจเชฅเซ€:

SELECT pg_sleep(10000);

เชนเชตเซ‡ เช†เชชเชฃเซ‡ เชเช• เช•เชพเช‰เชจเซเชŸเชฐเชจเซ€ เช•เชฟเช‚เชฎเชค เช˜เชฃเซ€, เช˜เชฃเซ€ เชตเช–เชค เช…เชชเชกเซ‡เชŸ เช•เชฐเซ€เช เช›เซ€เช. เชชเซเชฐเชฏเซ‹เช—เชจเซ€ เชถเซเชฆเซเชงเชคเชพ เชฎเชพเชŸเซ‡, เชšเชพเชฒเซ‹ เช† เช•เชฐเซ€เช dblink เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เช…เชฒเช— เชตเซเชฏเชตเชนเชพเชฐเซ‹เชฎเชพเช‚เชคเซ‡ เชตเชพเชธเซเชคเชตเชฟเช•เชคเชพเชฎเชพเช‚ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชฅเชถเซ‡:

DO $$
DECLARE
  i integer;
  tsb timestamp;
  tse timestamp;
  d double precision;
BEGIN
  PERFORM dblink_connect('dbname=' || current_database() || ' port=' || current_setting('port'));
  FOR i IN 1..10000 LOOP
    tsb = clock_timestamp();
    PERFORM dblink($e$UPDATE tbl SET v = v + 1 WHERE k = 'a';$e$);
    tse = clock_timestamp();
    IF i % 1000 = 0 THEN
      d = (extract('epoch' from tse) - extract('epoch' from tsb)) * 1000;
      RAISE NOTICE 'i = %, exectime = %', lpad(i::text, 5), lpad(d::text, 5);
    END IF;
  END LOOP;
  PERFORM dblink_disconnect();
END;
$$ LANGUAGE plpgsql;

NOTICE:  i =  1000, exectime = 0.524
NOTICE:  i =  2000, exectime = 0.739
NOTICE:  i =  3000, exectime = 1.188
NOTICE:  i =  4000, exectime = 2.508
NOTICE:  i =  5000, exectime = 1.791
NOTICE:  i =  6000, exectime = 2.658
NOTICE:  i =  7000, exectime = 2.318
NOTICE:  i =  8000, exectime = 2.572
NOTICE:  i =  9000, exectime = 2.929
NOTICE:  i = 10000, exectime = 3.808

เชถเซเช‚ เชฅเชฏเซเช‚? เชถเชพ เชฎเชพเชŸเซ‡ เชเช• เชฐเซ‡เช•เซ‹เชฐเซเชกเชจเชพ เชธเชฐเชณ เช…เชชเชกเซ‡เชŸ เชฎเชพเชŸเซ‡ เชชเชฃ เช…เชฎเชฒเชจเซ‹ เชธเชฎเชฏ 7 เช—เชฃเซ‹ เช“เช›เซ‹ เชฅเชฏเซ‹ โ€” 0.524ms เชฅเซ€ 3.808ms เชธเซเชงเซ€? เช…เชจเซ‡ เช…เชฎเชพเชฐเซเช‚ เชฐเซ‡เชŸเชฟเช‚เช— เชตเชงเซ เชจเซ‡ เชตเชงเซ เชงเซ€เชฎเซ‡ เชงเซ€เชฎเซ‡ เชฌเชจเซ€ เชฐเชนเซเชฏเซเช‚ เช›เซ‡.

เช† เชฌเชงเซ€ MVCCเชจเซ€ เชญเซ‚เชฒ เช›เซ‡.

เชคเซ‡ เชฌเชงเชพ เชตเชฟเชถเซ‡ เช›เซ‡ MVCC เชฎเชฟเช•เซ‡เชจเชฟเชเชฎ, เชœเซ‡ เช•เซเชตเซ‡เชฐเซ€ เชฎเชพเชŸเซ‡ เชเชจเซเชŸเซเชฐเซ€เชจเชพ เชชเชนเซ‡เชฒเชพเชจเชพเช‚ เชตเชฐเซเชเชจเชจเซ‡ เชœเซ‹เชตเชพเชจเซเช‚ เช•เชพเชฐเชฃ เชฌเชจเซ‡ เช›เซ‡. เชคเซ‹ เชšเชพเชฒเซ‹ เช†เชชเชฃเชพ เชŸเซ‡เชฌเชฒเชจเซ‡ โ€œเชกเซ‡เชกโ€ เชตเชฐเซเชเชจเชฎเชพเช‚เชฅเซ€ เชธเชพเชซ เช•เชฐเซ€เช:

VACUUM VERBOSE tbl;

INFO:  vacuuming "public.tbl"
INFO:  "tbl": found 0 removable, 10026 nonremovable row versions in 45 out of 45 pages
DETAIL:  10000 dead row versions cannot be removed yet, oldest xmin: 597439602

เช“เชน, เชธเชพเชซ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เช•เช‚เชˆ เชจเชฅเซ€! เชธเชฎเชพเช‚เชคเชฐ เชšเชพเชฒเซ€ เชฐเชนเซ‡เชฒ เชตเชฟเชจเช‚เชคเซ€ เช…เชฎเชพเชฐเซ€ เชธเชพเชฅเซ‡ เชฆเช–เชฒ เช•เชฐเซ€ เชฐเชนเซ€ เช›เซ‡ - เช›เซ‡เชตเชŸเซ‡, เชคเซ‡ เช•เซ‹เชˆ เชฆเชฟเชตเชธ เช† เชธเช‚เชธเซเช•เชฐเชฃเซ‹ เชคเชฐเชซ เชตเชณเชตเชพ เชฎเชพเช‚เช—เซ‡ เช›เซ‡ (เชถเซเช‚ เชœเซ‹?), เช…เชจเซ‡ เชคเซ‡ เชคเซ‡เชจเชพ เชฎเชพเชŸเซ‡ เช‰เชชเชฒเชฌเซเชง เชนเซ‹เชตเชพ เชœเซ‹เชˆเช. เช…เชจเซ‡ เชคเซ‡เชฅเซ€ เชตเซ‡เช•เซเชฏเซเชฎ เชซเซเชฒ เชชเชฃ เช†เชชเชฃเชจเซ‡ เชฎเชฆเชฆ เช•เชฐเชถเซ‡ เชจเชนเซ€เช‚.

เชŸเซ‡เชฌเชฒ "เชญเช‚เช—เซ€ เชฐเชนเซเชฏเซเช‚ เช›เซ‡".

เชชเชฐเช‚เชคเซ เช…เชฎเซ‡ เช–เชพเชคเชฐเซ€เชชเซ‚เชฐเซเชตเช• เชœเชพเชฃเซ€เช เช›เซ€เช เช•เซ‡ เชคเซ‡ เช•เซเชตเซ‡เชฐเซ€ เชฎเชพเชŸเซ‡ เช…เชฎเชพเชฐเชพ เชŸเซ‡เชฌเชฒเชจเซ€ เชœเชฐเซ‚เชฐ เชจเชฅเซ€. เชคเซ‡เชฅเซ€, เช…เชฎเซ‡ เชนเชœเซ€ เชชเชฃ เชŸเซ‡เชฌเชฒเชฎเชพเช‚เชฅเซ€ เชฌเชฟเชจเชœเชฐเซ‚เชฐเซ€ เชฆเชฐเซ‡เช• เชตเชธเซเชคเซเชจเซ‡ เชฆเซ‚เชฐ เช•เชฐเซ€เชจเซ‡ เชธเชฟเชธเซเชŸเชฎเชจเซ€ เช•เชพเชฎเช—เซ€เชฐเซ€เชจเซ‡ เชชเชฐเซเชฏเชพเชชเซเชค เชฎเชฐเซเชฏเชพเชฆเชพเชฎเชพเช‚ เชชเชฐเชค เช•เชฐเชตเชพเชจเซ‹ เชชเซเชฐเชฏเชพเชธ เช•เชฐเซ€เชถเซเช‚ - เช“เช›เชพเชฎเชพเช‚ เช“เช›เซเช‚ "เชฎเซ‡เชจเซเชฏเซเช…เชฒเซ€", เช•เชพเชฐเชฃ เช•เซ‡ VACUUM เช†เชชเซ‡ เช›เซ‡.

เชคเซ‡เชจเซ‡ เชตเชงเซ เชธเซเชชเชทเซเชŸ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡, เชšเชพเชฒเซ‹ เชฌเชซเชฐ เชŸเซ‡เชฌเชฒเชจเชพ เช•เซ‡เชธเชจเซเช‚ เช‰เชฆเชพเชนเชฐเชฃ เชœเซ‹เชˆเช. เชเชŸเชฒเซ‡ เช•เซ‡, INSERT/DELETE เชจเซ‹ เชฎเซ‹เชŸเซ‹ เชชเซเชฐเชตเชพเชน เช›เซ‡, เช…เชจเซ‡ เช•เซ‡เชŸเชฒเซ€เช•เชตเชพเชฐ เชŸเซ‡เชฌเชฒ เชธเช‚เชชเซ‚เชฐเซเชฃเชชเชฃเซ‡ เช–เชพเชฒเซ€ เชนเซ‹เชฏ เช›เซ‡. เชชเชฐเช‚เชคเซ เชœเซ‹ เชคเซ‡ เช–เชพเชฒเซ€ เชจเชฅเซ€, เชคเซ‹ เช†เชชเชฃเซ‡ เชœเซ‹เชˆเช เชคเซ‡เชจเซ€ เชตเชฐเซเชคเชฎเชพเชจ เชธเชพเชฎเช—เซเชฐเซ€ เชธเชพเชšเชตเซ‹.

#0: เชชเชฐเชฟเชธเซเชฅเชฟเชคเชฟเชจเซเช‚ เชฎเซ‚เชฒเซเชฏเชพเช‚เช•เชจ

เชคเซ‡ เชธเซเชชเชทเซเชŸ เช›เซ‡ เช•เซ‡ เชคเชฎเซ‡ เชฆเชฐเซ‡เช• เช‘เชชเชฐเซ‡เชถเชจ เชชเช›เซ€ เชชเชฃ เชŸเซ‡เชฌเชฒ เชธเชพเชฅเซ‡ เช•เช‚เชˆเช• เช•เชฐเชตเชพเชจเซ‹ เชชเซเชฐเชฏเชพเชธ เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹, เชชเชฐเช‚เชคเซ เช†เชจเซ‹ เช•เซ‹เชˆ เช…เชฐเซเชฅ เชจเชฅเซ€ - เชœเชพเชณเชตเชฃเซ€ เช“เชตเชฐเชนเซ‡เชก เชธเซเชชเชทเซเชŸเชชเชฃเซ‡ เชฒเช•เซเชทเซเชฏ เชชเซเชฐเชถเซเชจเซ‹เชจเชพ เชฅเซเชฐเซเชชเซเชŸ เช•เชฐเชคเชพเช‚ เชตเชงเซ เชนเชถเซ‡.

เชšเชพเชฒเซ‹ เชฎเชพเชชเชฆเช‚เชกเซ‹ เช˜เชกเซ€เช - "เชคเซ‡ เช•เชพเชฐเซเชฏ เช•เชฐเชตเชพเชจเซ‹ เชธเชฎเชฏ เช›เซ‡" เชœเซ‹:

  • VACUUM เช˜เชฃเชพ เชธเชฎเชฏ เชชเชนเซ‡เชฒเชพ เชฒเซ‹เชจเซเชš เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซเช‚ เชนเชคเซเช‚
    เช…เชฎเซ‡ เชญเชพเชฐเซ‡ เชญเชพเชฐเชจเซ€ เช…เชชเซ‡เช•เซเชทเชพ เชฐเชพเช–เซ€เช เช›เซ€เช, เชคเซ‡เชฅเซ€ เชคเซ‡ เชฅเชตเชพ เชฆเซ‹ 60 เชธเซ‡เช•เช‚เชก เช›เซ‡เชฒเซเชฒเชพ [เช“เชŸเซ‹]เชตเซ‡เช•เซเชฏเซเชฎเชฅเซ€.
  • เชญเซŒเชคเชฟเช• เชŸเซ‡เชฌเชฒเชจเซเช‚ เช•เชฆ เชฒเช•เซเชทเซเชฏ เช•เชฐเชคเชพเช‚ เชฎเซ‹เชŸเซเช‚ เช›เซ‡
    เชšเชพเชฒเซ‹ เชคเซ‡เชจเซ‡ เชฒเช˜เซเชคเซเชคเชฎ เช•เชฆเชจเซ€ เชคเซเชฒเชจเชพเชฎเชพเช‚ เชชเซƒเชทเซเช เซ‹เชจเซ€ เชธเช‚เช–เซเชฏเชพเชจเชพ เชฌเชฎเชฃเชพ (8KB เชฌเซเชฒเซ‹เช•เซเชธ) เชคเชฐเซ€เช•เซ‡ เชตเซเชฏเชพเช–เซเชฏเชพเชฏเชฟเชค เช•เชฐเซ€เช - เชขเช—เชฒเชพ เชฎเชพเชŸเซ‡ 1 blk + เชฆเชฐเซ‡เช• เช‡เชจเซเชกเซ‡เช•เซเชธ เชฎเชพเชŸเซ‡ 1 blk - เชธเช‚เชญเชตเชฟเชค เช–เชพเชฒเซ€ เชŸเซ‡เชฌเชฒ เชฎเชพเชŸเซ‡. เชœเซ‹ เช†เชชเชฃเซ‡ เช…เชชเซ‡เช•เซเชทเชพ เชฐเชพเช–เซ€เช เช›เซ€เช เช•เซ‡ เชกเซ‡เชŸเชพเชจเซ‹ เชšเซ‹เช•เซเช•เชธ เชœเชฅเซเชฅเซ‹ เชนเช‚เชฎเซ‡เชถเชพ "เชธเชพเชฎเชพเชจเซเชฏ เชฐเซ€เชคเซ‡" เชฌเชซเชฐเชฎเชพเช‚ เชฐเชนเซ‡เชถเซ‡, เชคเซ‹ เช† เชธเซ‚เชคเซเชฐเชฎเชพเช‚ เชซเซ‡เชฐเชซเชพเชฐ เช•เชฐเชตเซ‹ เชตเชพเชœเชฌเซ€ เช›เซ‡.

เชšเช•เชพเชธเชฃเซ€ เชตเชฟเชจเช‚เชคเซ€

SELECT
  relpages
, ((
    SELECT
      count(*)
    FROM
      pg_index
    WHERE
      indrelid = cl.oid
  ) + 1) << 13 size_norm -- ั‚ัƒั‚ ะฟั€ะฐะฒะธะปัŒะฝะตะต ะดะตะปะฐั‚ัŒ * current_setting('block_size')::bigint, ะฝะพ ะบั‚ะพ ะผะตะฝัะตั‚ ั€ะฐะทะผะตั€ ะฑะปะพะบะฐ?..
, pg_total_relation_size(oid) size
, coalesce(extract('epoch' from (now() - greatest(
    pg_stat_get_last_vacuum_time(oid)
  , pg_stat_get_last_autovacuum_time(oid)
  ))), 1 << 30) vaclag
FROM
  pg_class cl
WHERE
  oid = $1::regclass -- tbl
LIMIT 1;

relpages | size_norm | size    | vaclag
-------------------------------------------
       0 |     24576 | 1105920 | 3392.484835

#1: เชนเชœเซ เชชเชฃ เชตเซ‡เช•เซเชฏเซเชฎ

เช…เชฎเซ‡ เช…เช—เชพเช‰เชฅเซ€ เชœเชพเชฃเซ€ เชถเช•เชคเชพ เชจเชฅเซ€ เช•เซ‡ เชถเซเช‚ เชธเชฎเชพเช‚เชคเชฐ เช•เซเชตเซ‡เชฐเซ€ เช…เชฎเชพเชฐเซ€ เชธเชพเชฅเซ‡ เชจเซ‹เช‚เชงเชชเชพเชคเซเชฐ เชฐเซ€เชคเซ‡ เชฆเช–เชฒ เช•เชฐเซ€ เชฐเชนเซ€ เช›เซ‡ - เชคเซ‡ เชถเชฐเซ‚ เชฅเชฏเชพ เชชเช›เซ€ เช•เซ‡เชŸเชฒเชพ เชฐเซ‡เช•เซ‹เชฐเซเชก "เชœเซ‚เชจเชพ" เชฅเชˆ เช—เชฏเชพ เช›เซ‡. เชคเซ‡เชฅเซ€, เชœเซเชฏเชพเชฐเซ‡ เช†เชชเชฃเซ‡ เช•เซ‹เชˆเช• เชฐเซ€เชคเซ‡ เชŸเซ‡เชฌเชฒ เชชเชฐ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เช•เชฐเชตเชพเชจเซเช‚ เชจเช•เซเช•เซ€ เช•เชฐเซ€เช เช›เซ€เช, เช•เซ‹เชˆ เชชเชฃ เชธเช‚เชœเซ‹เช—เซ‹เชฎเชพเช‚, เช†เชชเชฃเซ‡ เชธเซŒ เชชเซเชฐเชฅเชฎ เชคเซ‡เชจเชพ เชชเชฐ เช…เชฎเชฒ เช•เชฐเชตเซ‹ เชœเซ‹เชˆเช เชตเชพเชฏเซเชฎเซเชฏเซเชฎ - VACUUM FULL เชฅเซ€ เชตเชฟเชชเชฐเซ€เชค, เชคเซ‡ เชตเชพเช‚เชšเชตเชพ-เชฒเซ‡เช–เชตเชพ เชกเซ‡เชŸเชพ เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเชคเซ€ เชธเชฎเชพเช‚เชคเชฐ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพเช“เชฎเชพเช‚ เชฆเช–เชฒ เช•เชฐเชคเซเช‚ เชจเชฅเซ€.

เชคเซ‡ เชœ เชธเชฎเชฏเซ‡, เชคเซ‡ เช…เชฎเซ‡ เชœเซ‡ เชฆเซ‚เชฐ เช•เชฐเชตเชพ เชฎเชพเช‚เช—เซ€เช เช›เซ€เช เชคเซ‡เชฎเชพเช‚เชฅเซ€ เชฎเซ‹เชŸเชพ เชญเชพเช—เชจเซ‡ เชคเชฐเชค เชœ เชธเชพเชซ เช•เชฐเซ€ เชถเช•เซ‡ เช›เซ‡. เชนเชพ, เช…เชจเซ‡ เช† เชŸเซ‡เชฌเชฒ เชชเชฐเชจเชพ เช…เชจเซเช—เชพเชฎเซ€ เชชเซเชฐเชถเซเชจเซ‹ เช…เชฎเชพเชฐเซ€ เชชเชพเชธเซ‡ เชœเชถเซ‡ "เชนเซ‹เชŸ เช•เซ‡เชถ" เชฆเซเชตเชพเชฐเชพ, เชœเซ‡ เชคเซ‡เชฎเชจเซ€ เช…เชตเชงเชฟ เช˜เชŸเชพเชกเชถเซ‡ - เช…เชจเซ‡ เชคเซ‡เชฅเซ€, เช…เชฎเชพเชฐเชพ เชธเชฐเซเชตเชฟเชธเชฟเช‚เช— เชŸเซเชฐเชพเชจเซเชเซ‡เช•เซเชถเชจ เชฆเซเชตเชพเชฐเชพ เช…เชจเซเชฏ เชฒเซ‹เช•เซ‹เชจเซ‡ เช…เชตเชฐเซ‹เชงเชฟเชค เช•เชฐเชตเชพเชจเซ‹ เช•เซเชฒ เชธเชฎเชฏ.

#2: เช•เซ‹เชˆ เช˜เชฐเซ‡ เช›เซ‡?

เชšเชพเชฒเซ‹ เชคเชชเชพเชธเซ€เช เช•เซ‡ เช•เซ‹เชทเซเชŸเช•เชฎเชพเช‚ เช•เช‚เชˆเชชเชฃ เช›เซ‡ เช•เซ‡ เช•เซ‡เชฎ:

TABLE tbl LIMIT 1;

เชœเซ‹ เชคเซเชฏเชพเช‚ เชเช• เชชเชฃ เชฐเซ‡เช•เซ‹เชฐเซเชก เชฌเชพเช•เซ€ เชจ เชนเซ‹เชฏ, เชคเซ‹ เช…เชฎเซ‡ เชซเช•เซเชค เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เช•เชฐเซ€เชจเซ‡ เช˜เชฃเซเช‚ เชฌเชšเชพเชตเซ€ เชถเช•เซ€เช เช›เซ€เช เชŸเซเชฐเช‚เช•เชพเช‡เชŸ:

เชคเซ‡ เชฆเชฐเซ‡เช• เชŸเซ‡เชฌเชฒ เชฎเชพเชŸเซ‡ เชฌเชฟเชจเชถเชฐเชคเซ€ เชกเชฟเชฒเซ€เชŸ เช•เชฎเชพเชจเซเชกเชจเซ€ เชœเซ‡เชฎ เชœ เช•เชพเชฐเซเชฏ เช•เชฐเซ‡ เช›เซ‡, เชชเชฐเช‚เชคเซ เชคเซ‡ เชตเชงเซ เชเชกเชชเซ€ เช›เซ‡ เช•เชพเชฐเชฃ เช•เซ‡ เชคเซ‡ เช–เชฐเซ‡เช–เชฐ เช•เซ‹เชทเซเชŸเช•เซ‹เชจเซ‡ เชธเซเช•เซ‡เชจ เช•เชฐเชคเซเช‚ เชจเชฅเซ€. เชคเชฆเซเชชเชฐเชพเช‚เชค, เชคเซ‡ เชคเชฐเชค เชœ เชกเชฟเชธเซเช• เชœเช—เซเชฏเชพ เช–เชพเชฒเซ€ เช•เชฐเซ‡ เช›เซ‡, เชคเซ‡เชฅเซ€ เชชเช›เซ€เชฅเซ€ เชตเซ‡เช•เซเชฏเซเชฎ เช“เชชเชฐเซ‡เชถเชจ เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เชจเชฅเซ€.

เชคเชฎเชพเชฐเซ‡ เชŸเซ‡เชฌเชฒ เชธเชฟเช•เซเชตเชจเซเชธ เช•เชพเช‰เชจเซเชŸเชฐ เชฐเซ€เชธเซ‡เชŸ เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡ เช•เซ‡ เช•เซ‡เชฎ เชคเซ‡ เชจเช•เซเช•เซ€ เช•เชฐเชตเชพเชจเซเช‚ เชคเชฎเชพเชฐเชพ เชชเชฐ เช›เซ‡.

#3: เชฆเชฐเซ‡เช• เชตเซเชฏเช•เซเชคเชฟ - เชตเชณเชพเช‚เช• เชฒเซ‹!

เช…เชฎเซ‡ เช…เชคเซเชฏเช‚เชค เชธเซเชชเชฐเซเชงเชพเชคเซเชฎเช• เชตเชพเชคเชพเชตเชฐเชฃเชฎเชพเช‚ เช•เชพเชฎ เช•เชฐเชคเชพ เชนเซ‹เชตเชพเชฅเซ€, เชœเซเชฏเชพเชฐเซ‡ เช…เชฎเซ‡ เช…เชนเซ€เช‚ เชคเชชเชพเชธ เช•เชฐเซ€ เชฐเชนเซเชฏเชพ เช›เซ€เช เช•เซ‡ เช•เซ‹เชทเซเชŸเช•เชฎเชพเช‚ เช•เซ‹เชˆ เชเชจเซเชŸเซเชฐเซ€ เชจเชฅเซ€, เชคเซเชฏเชพเช‚ เช•เซ‹เชˆเช เชชเชนเซ‡เชฒเซ‡เชฅเซ€ เชœ เช•เช‚เชˆเช• เชฒเช–เซเชฏเซเช‚ เชนเชถเซ‡. เช†เชชเชฃเซ‡ เช† เชฎเชพเชนเชฟเชคเซ€ เช—เซเชฎเชพเชตเชตเซ€ เชœเซ‹เชˆเช เชจเชนเซ€เช‚, เชคเซ‹ เชถเซเช‚? เชคเซ‡ เชธเชพเชšเซเช‚ เช›เซ‡, เช†เชชเชฃเซ‡ เช–เชพเชคเชฐเซ€ เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡ เช•เซ‡ เช•เซ‹เชˆ เชคเซ‡เชจเซ‡ เช–เชพเชคเชฐเซ€ เชฎเชพเชŸเซ‡ เชฒเช–เซ€ เชจ เชถเช•เซ‡.

เช† เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เช†เชชเชฃเซ‡ เชธเช•เซเชทเชฎ เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡ เช—เช‚เชญเซ€เชฐ-เช…เชฎเชพเชฐเชพ เชตเซเชฏเชตเชนเชพเชฐ เชฎเชพเชŸเซ‡ เช…เชฒเช—เชคเชพ (เชนเชพ, เช…เชนเซ€เช‚ เช†เชชเชฃเซ‡ เชตเซเชฏเชตเชนเชพเชฐ เชถเชฐเซ‚ เช•เชฐเซ€เช เช›เซ€เช) เช…เชจเซ‡ เชŸเซ‡เชฌเชฒเชจเซ‡ "เชšเซเชธเซเชคเชชเชฃเซ‡" เชฒเซ‰เช• เช•เชฐเซ€เช เช›เซ€เช:

BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
LOCK TABLE tbl IN ACCESS EXCLUSIVE MODE;

เชฌเซเชฒเซ‹เช•เซ€เช‚เช—เชจเซเช‚ เช† เชธเซเชคเชฐ เชคเซ‡ เช“เชชเชฐเซ‡เชถเชจเซเชธ เชฆเซเชตเชพเชฐเชพ เชจเช•เซเช•เซ€ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡ เชœเซ‡ เช…เชฎเซ‡ เชคเซ‡เชจเชพ เชชเชฐ เช•เชฐเชตเชพ เชฎเชพเช‚เช—เซ€เช เช›เซ€เช.

#4: เชนเชฟเชคเซ‹เชจเซ‹ เชธเช‚เช˜เชฐเซเชท

เช…เชฎเซ‡ เช…เชนเซ€เช‚ เช†เชตเซ€เช เช›เซ€เช เช…เชจเซ‡ เชšเชฟเชนเซเชจเชจเซ‡ "เชฒเซ‹เช•" เช•เชฐเชตเชพ เชฎเชพเช‚เช—เซ€เช เช›เซ€เช - เชœเซ‹ เชคเซ‡ เช•เซเชทเชฃเซ‡ เช•เซ‹เชˆ เชคเซ‡เชจเชพ เชชเชฐ เชธเช•เซเชฐเชฟเชฏ เชนเซ‹เชฏ, เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เชคเซ‡เชฎเชพเช‚เชฅเซ€ เชตเชพเช‚เชšเชตเซเช‚? เช…เชฎเซ‡ เช† เชฌเซเชฒเซ‹เช• เชฐเชฟเชฒเซ€เช เชฅเชตเชพเชจเซ€ เชฐเชพเชน เชœเซ‹เชˆเชจเซ‡ "เช…เชŸเช•เซ€" เชœเชˆเชถเซเช‚, เช…เชจเซ‡ เช…เชจเซเชฏ เชฒเซ‹เช•เซ‹ เชœเซ‡ เชตเชพเช‚เชšเชตเชพ เชฎเชพเช‚เช—เซ‡ เช›เซ‡ เชคเซ‡ เช…เชฎเชพเชฐเซ€ เชชเชพเชธเซ‡ เช†เชตเชถเซ‡...

เช†เชตเซเช‚ เชจ เชฅเชพเชฏ เชคเซ‡ เชฎเชพเชŸเซ‡, เช…เชฎเซ‡ "เชชเซ‹เชคเชพเชจเซ‡ เชฌเชฒเชฟเชฆเชพเชจ เช†เชชเซ€เชถเซเช‚" - เชœเซ‹ เช†เชชเชฃเซ‡ เชšเซ‹เช•เซเช•เชธ (เชธเซเชตเซ€เช•เชพเชฐเซเชฏ เชŸเซ‚เช‚เช•เชพ) เชธเชฎเชฏเชจเซ€ เช…เช‚เชฆเชฐ เชคเชพเชณเซเช‚ เชฎเซ‡เชณเชตเชตเชพเชฎเชพเช‚ เช…เชธเชฎเชฐเซเชฅ เชนเซ‹เชค, เชคเซ‹ เชชเช›เซ€ เช…เชฎเชจเซ‡ เช†เชงเชพเชฐ เชคเชฐเชซเชฅเซ€ เช…เชชเชตเชพเชฆ เชชเซเชฐเชพเชชเซเชค เชฅเชถเซ‡, เชชเชฐเช‚เชคเซ เช“เช›เชพเชฎเชพเช‚ เช“เช›เซเช‚ เช…เชฎเซ‡ เชคเซ‡เชฎเชพเช‚ เชตเชงเซ เชฆเช–เชฒ เช•เชฐเซ€เชถเซเช‚ เชจเชนเซ€เช‚. เช…เชจเซเชฏ

เช† เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡, เชธเชคเซเชฐ เชšเชฒ เชธเซ‡เชŸ เช•เชฐเซ‹ lock_timeout (9.3+ เช†เชตเซƒเชคเซเชคเชฟเช“ เชฎเชพเชŸเซ‡) เช…เชฅเชตเชพ/เช…เชจเซ‡ เชธเซเชŸเซ‡เชŸเชฎเซ‡เชจเซเชŸ_เชธเชฎเชฏเชธเชฎเชพเชชเซเชค. เชฏเชพเชฆ เชฐเชพเช–เชตเชพเชจเซ€ เชฎเซเช–เซเชฏ เชตเชธเซเชคเซ เช เช›เซ‡ เช•เซ‡ เชธเซเชŸเซ‡เชŸเชฎเซ‡เชจเซเชŸ_เชŸเชพเช‡เชฎเช†เช‰เชŸ เชฎเซ‚เชฒเซเชฏ เชซเช•เซเชค เช†เช—เชฒเชพ เชจเชฟเชตเซ‡เชฆเชจเชฅเซ€ เชœ เชฒเชพเช—เซ เชฅเชพเชฏ เช›เซ‡. เชเชŸเชฒเซ‡ เช•เซ‡, เช—เซเชฒเซเช‡เช‚เช—เชฎเชพเช‚ เช†เชจเซ€ เชœเซ‡เชฎ - เช•เชพเชฎ เช•เชฐเชถเซ‡ เชจเชนเซ€เช‚:

SET statement_timeout = ...;LOCK TABLE ...;

เชตเซ‡เชฐเซ€เชเชฌเชฒเชจเชพ "เชœเซ‚เชจเชพ" เชฎเซ‚เชฒเซเชฏเชจเซ‡ เชชเช›เซ€เชฅเซ€ เชชเซเชจเชƒเชธเซเชฅเชพเชชเชฟเชค เช•เชฐเชตเชพ เชธเชพเชฅเซ‡ เชตเซเชฏเชตเชนเชพเชฐ เชจ เช•เชฐเชตเซ‹ เชชเชกเซ‡ เชคเซ‡ เชฎเชพเชŸเซ‡, เช…เชฎเซ‡ เชซเซ‹เชฐเซเชฎเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เช เช›เซ€เช เชธเซเชฅเชพเชจเชฟเช• เชธเซ‡เชŸ เช•เชฐเซ‹, เชœเซ‡ เชธเซ‡เชŸเชฟเช‚เช—เชจเชพ เช…เชตเช•เชพเชถเชจเซ‡ เชตเชฐเซเชคเชฎเชพเชจ เชตเซเชฏเชตเชนเชพเชฐ เชธเซเชงเซ€ เชฎเชฐเซเชฏเชพเชฆเชฟเชค เช•เชฐเซ‡ เช›เซ‡.

เช…เชฎเชจเซ‡ เชฏเชพเชฆ เช›เซ‡ เช•เซ‡ เชธเซเชŸเซ‡เชŸเชฎเซ‡เชจเซเชŸ_เชŸเชพเช‡เชฎเช†เช‰เชŸ เช เชฌเชงเซ€ เช…เชจเซเช—เชพเชฎเซ€ เชตเชฟเชจเช‚เชคเซ€เช“ เชชเชฐ เชฒเชพเช—เซ เชฅเชพเชฏ เช›เซ‡ เชœเซ‡เชฅเซ€ เช•เชฐเซ€เชจเซ‡ เชœเซ‹ เช•เซ‹เชทเซเชŸเช•เชฎเชพเช‚ เช˜เชฃเซ‹ เชกเซ‡เชŸเชพ เชนเซ‹เชฏ เชคเซ‹ เชตเซเชฏเชตเชนเชพเชฐ เช…เชธเซเชตเซ€เช•เชพเชฐเซเชฏ เชฎเซ‚เชฒเซเชฏเซ‹ เชธเซเชงเซ€ เชฒเช‚เชฌเชพเชตเซ€ เชจ เชถเช•เซ‡.

#5: เชกเซ‡เชŸเชพ เช•เซ‰เชชเชฟ เช•เชฐเซ‹

เชœเซ‹ เช•เซ‹เชทเซเชŸเช• เชธเช‚เชชเซ‚เชฐเซเชฃเชชเชฃเซ‡ เช–เชพเชฒเซ€ เชจ เชนเซ‹เชฏ, เชคเซ‹ เชธเชนเชพเชฏเช• เช…เชธเซเชฅเชพเชฏเซ€ เช•เซ‹เชทเซเชŸเช•เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เชกเซ‡เชŸเชพเชจเซ‡ เชซเชฐเซ€เชฅเซ€ เชธเชพเชšเชตเชตเซ‹ เชชเชกเชถเซ‡:

CREATE TEMPORARY TABLE _tmp_swap ON COMMIT DROP AS TABLE tbl;

เชธเชนเซ€ เช•เชฎเซ€เชŸ เชกเซเชฐเซ‹เชช เชชเชฐ เชฎเชคเชฒเชฌ เช•เซ‡ เชตเซเชฏเชตเชนเชพเชฐ เชธเชฎเชพเชชเซเชค เชฅเชพเชฏ เชคเซ‡ เช•เซเชทเชฃเซ‡, เช…เชธเซเชฅเชพเชฏเซ€ เช•เซ‹เชทเซเชŸเช• เช…เชธเซเชคเชฟเชคเซเชตเชฎเชพเช‚ เชฌเช‚เชง เชฅเชˆ เชœเชถเซ‡, เช…เชจเซ‡ เช•เชจเซ‡เช•เซเชถเชจ เชธเช‚เชฆเชฐเซเชญเชฎเชพเช‚ เชคเซ‡เชจเซ‡ เชฎเซ‡เชจเซเชฏเซเช…เชฒเซ€ เช•เชพเชขเซ€ เชจเชพเช–เชตเชพเชจเซ€ เช•เซ‹เชˆ เชœเชฐเซ‚เชฐ เชจเชฅเซ€.

เช…เชฎเซ‡ เชงเชพเชฐเซ€เช เช›เซ€เช เช•เซ‡ เชคเซเชฏเชพเช‚ เช˜เชฃเซ‹ "เชฒเชพเช‡เชต" เชกเซ‡เชŸเชพ เชจเชฅเซ€, เช† เช‘เชชเชฐเซ‡เชถเชจ เช–เซ‚เชฌ เชเชกเชชเชฅเซ€ เชฅเชตเซเช‚ เชœเซ‹เชˆเช.

เชธเชพเชฐเซเช‚, เชคเซ‡ เชฌเชงเซ เชœ เช›เซ‡! เชตเซเชฏเชตเชนเชพเชฐ เชชเซ‚เชฐเซเชฃ เช•เชฐเซเชฏเชพ เชชเช›เซ€ เชญเซ‚เชฒเชถเซ‹ เชจเชนเซ€เช‚ เชตเชฟเชถเซเชฒเซ‡เชทเชฃ เชšเชฒเชพเชตเซ‹ เชœเซ‹ เชœเชฐเซ‚เชฐเซ€ เชนเซ‹เชฏ เชคเซ‹ เช•เซ‹เชทเซเชŸเช•เชจเชพ เช†เช‚เช•เชกเชพเช“เชจเซ‡ เชธเชพเชฎเชพเชจเซเชฏ เชฌเชจเชพเชตเชตเชพ เชฎเชพเชŸเซ‡.

เช…เช‚เชคเชฟเชฎ เชธเซเช•เซเชฐเชฟเชชเซเชŸ เชเช•เชธเชพเชฅเซ‡ เชฎเซ‚เช•เชตเซ€

เช…เชฎเซ‡ เช† "เชธเซเชฏเซเชกเซ‹-เชชเชพเชฏเชฅเซ‹เชจ" เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เช เช›เซ€เช:

# ัะพะฑะธั€ะฐะตะผ ัั‚ะฐั‚ะธัั‚ะธะบัƒ ั ั‚ะฐะฑะปะธั†ั‹
stat <-
  SELECT
    relpages
  , ((
      SELECT
        count(*)
      FROM
        pg_index
      WHERE
        indrelid = cl.oid
    ) + 1) << 13 size_norm
  , pg_total_relation_size(oid) size
  , coalesce(extract('epoch' from (now() - greatest(
      pg_stat_get_last_vacuum_time(oid)
    , pg_stat_get_last_autovacuum_time(oid)
    ))), 1 << 30) vaclag
  FROM
    pg_class cl
  WHERE
    oid = $1::regclass -- table_name
  LIMIT 1;

# ั‚ะฐะฑะปะธั†ะฐ ะฑะพะปัŒัˆะต ั†ะตะปะตะฒะพะณะพ ั€ะฐะทะผะตั€ะฐ ะธ VACUUM ะฑั‹ะป ะดะฐะฒะฝะพ
if stat.size > 2 * stat.size_norm and stat.vaclag is None or stat.vaclag > 60:
  -> VACUUM %table;
  try:
    -> BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    # ะฟั‹ั‚ะฐะตะผัั ะทะฐั…ะฒะฐั‚ะธั‚ัŒ ะผะพะฝะพะฟะพะปัŒะฝัƒัŽ ะฑะปะพะบะธั€ะพะฒะบัƒ ั ะฟั€ะตะดะตะปัŒะฝั‹ะผ ะฒั€ะตะผะตะฝะตะผ ะพะถะธะดะฐะฝะธั 1s
    -> SET LOCAL statement_timeout = '1s'; SET LOCAL lock_timeout = '1s';
    -> LOCK TABLE %table IN ACCESS EXCLUSIVE MODE;
    # ะฝะฐะดะพ ัƒะฑะตะดะธั‚ัŒัั ะฒ ะฟัƒัั‚ะพั‚ะต ั‚ะฐะฑะปะธั†ั‹ ะฒะฝัƒั‚ั€ะธ ั‚ั€ะฐะฝะทะฐะบั†ะธะธ ั ะฑะปะพะบะธั€ะพะฒะบะพะน
    row <- TABLE %table LIMIT 1;
    # ะตัะปะธ ะฒ ั‚ะฐะฑะปะธั†ะต ะฝะตั‚ ะฝะธ ะพะดะฝะพะน "ะถะธะฒะพะน" ะทะฐะฟะธัะธ - ะพั‡ะธั‰ะฐะตะผ ะตะต ะฟะพะปะฝะพัั‚ัŒัŽ, ะฒ ะฟั€ะพั‚ะธะฒะฝะพะผ ัะปัƒั‡ะฐะต - "ะฟะตั€ะตะฒัั‚ะฐะฒะปัะตะผ" ะฒัะต ะทะฐะฟะธัะธ ั‡ะตั€ะตะท ะฒั€ะตะผะตะฝะฝัƒัŽ ั‚ะฐะฑะปะธั†ัƒ
    if row is None:
      -> TRUNCATE TABLE %table RESTART IDENTITY;
    else:
      # ัะพะทะดะฐะตะผ ะฒั€ะตะผะตะฝะฝัƒัŽ ั‚ะฐะฑะปะธั†ัƒ ั ะดะฐะฝะฝั‹ะผะธ ั‚ะฐะฑะปะธั†ั‹-ะพั€ะธะณะธะฝะฐะปะฐ
      -> CREATE TEMPORARY TABLE _tmp_swap ON COMMIT DROP AS TABLE %table;
      # ะพั‡ะธั‰ะฐะตะผ ะพั€ะธะณะธะฝะฐะป ะฑะตะท ัะฑั€ะพัะฐ ะฟะพัะปะตะดะพะฒะฐั‚ะตะปัŒะฝะพัั‚ะธ
      -> TRUNCATE TABLE %table;
      # ะฒัั‚ะฐะฒะปัะตะผ ะฒัะต ัะพั…ั€ะฐะฝะตะฝะฝั‹ะต ะฒะพ ะฒั€ะตะผะตะฝะฝะพะน ั‚ะฐะฑะปะธั†ะต ะดะฐะฝะฝั‹ะต ะพะฑั€ะฐั‚ะฝะพ
      -> INSERT INTO %table TABLE _tmp_swap;
    -> COMMIT;
  except Exception as e:
    # ะตัะปะธ ะผั‹ ะฟะพะปัƒั‡ะธะปะธ ะพัˆะธะฑะบัƒ, ะฝะพ ัะพะตะดะธะฝะตะฝะธะต ะฒัะต ะตั‰ะต "ะถะธะฒะพ" - ัะปะพะฒะธะปะธ ั‚ะฐะนะผะฐัƒั‚
    if not isinstance(e, InterfaceError):
      -> ROLLBACK;

เชถเซเช‚ เชฌเซ€เชœเซ€ เชตเชพเชฐ เชกเซ‡เชŸเชพเชจเซ€ เชจเช•เชฒ เชจ เช•เชฐเชตเซ€ เชถเช•เซเชฏ เช›เซ‡?เชธเซˆเชฆเซเชงเชพเช‚เชคเชฟเช• เชฐเซ€เชคเซ‡, เชคเซ‡ เชถเช•เซเชฏ เช›เซ‡ เชœเซ‹ เชŸเซ‡เชฌเชฒเชจเซ‹ oid เชชเซ‹เชคเซ‡ BL เชฌเชพเชœเซเชจเซ€ เช…เชจเซเชฏ เช•เซ‹เชˆเชชเชฃ เชชเซเชฐเชตเซƒเชคเซเชคเชฟเช“ เชธเชพเชฅเซ‡ เช…เชฅเชตเชพ DB เชฌเชพเชœเซเชฅเซ€ FK เชธเชพเชฅเซ‡ เชœเซ‹เชกเชพเชฏเซ‡เชฒ เชจ เชนเซ‹เชฏ:

CREATE TABLE _swap_%table(LIKE %table INCLUDING ALL);
INSERT INTO _swap_%table TABLE %table;
DROP TABLE %table;
ALTER TABLE _swap_%table RENAME TO %table;

เชšเชพเชฒเซ‹ เชธเซเชคเซเชฐเซ‹เชค เชŸเซ‡เชฌเชฒ เชชเชฐ เชธเซเช•เซเชฐเชฟเชชเซเชŸ เชšเชฒเชพเชตเซ€เช เช…เชจเซ‡ เชฎเซ‡เชŸเซเชฐเชฟเช•เซเชธ เชคเชชเชพเชธเซ€เช:

VACUUM tbl;
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
  SET LOCAL statement_timeout = '1s'; SET LOCAL lock_timeout = '1s';
  LOCK TABLE tbl IN ACCESS EXCLUSIVE MODE;
  CREATE TEMPORARY TABLE _tmp_swap ON COMMIT DROP AS TABLE tbl;
  TRUNCATE TABLE tbl;
  INSERT INTO tbl TABLE _tmp_swap;
COMMIT;

relpages | size_norm | size   | vaclag
-------------------------------------------
       0 |     24576 |  49152 | 32.705771

เชฌเชงเซเช‚ เช•เชพเชฎ เช•เชฐเซเชฏเซเช‚! เช•เซ‹เชทเซเชŸเช• 50 เชตเช–เชค เชธเช‚เช•เซ‹เชšเชพเชˆ เช—เชฏเซเช‚ เช›เซ‡ เช…เชจเซ‡ เชคเชฎเชพเชฎ เช…เชชเชกเซ‡เชŸเซเชธ เชซเชฐเซ€เชฅเซ€ เชเชกเชชเชฅเซ€ เชšเชพเชฒเซ€ เชฐเชนเซเชฏเชพ เช›เซ‡.

เชธเซ‹เชฐเซเชธ: www.habr.com

เชเช• เชŸเชฟเชชเซเชชเชฃเซ€ เช‰เชฎเซ‡เชฐเซ‹