рдЬреЗрд╡реНрд╣рд╛ рд╡реНрд╣реЕрдХреНрдпреВрдо рдЕрдпрд╢рд╕реНрд╡реА рд╣реЛрддреЛ, рддреЗрд╡реНрд╣рд╛ рдЖрдореНрд╣реА рдЯреЗрдмрд▓ рд╕реНрд╡рд╣рд╕реНрддреЗ рд╕рд╛рдл рдХрд░рддреЛ

рдкреЛрдХрд│реА PostgreSQL рдордзреАрд▓ рдЯреЗрдмрд▓рдордзреВрди рдлрдХреНрдд рдХрд╛рдп "рд╕рд╛рдл" рдХрд░реВ рд╢рдХрддреЗ рдХреЛрдгреАрд╣реА рдкрд╛рд╣реВ рд╢рдХрдд рдирд╛рд╣реА - рдореНрд╣рдгрдЬреЗ, рд╣реЗ рд░реЗрдХреЙрд░реНрдб рдмрджрд▓рдгреНрдпрд╛рдкреВрд░реНрд╡реА рд╕реБрд░реВ рдЭрд╛рд▓реЗрд▓реА рдПрдХрд╣реА рд╕рдХреНрд░рд┐рдп рд╡рд┐рдирдВрддреА рдирд╛рд╣реА.

рдкрд░рдВрддреБ рдЕрд╕рд╛ рдЕрдкреНрд░рд┐рдп рдкреНрд░рдХрд╛рд░ (OLTP рдбреЗрдЯрд╛рдмреЗрд╕рд╡рд░ рджреАрд░реНрдШрдХрд╛рд▓реАрди OLAP рд▓реЛрдб) рдЕрджреНрдпрд╛рдк рдЕрд╕реНрддрд┐рддреНрд╡рд╛рдд рдЕрд╕рд▓реНрдпрд╛рд╕ рдХрд╛рдп? рдХрд╕реЗ рд╕рдХреНрд░рд┐рдпрдкрдгреЗ рдмрджрд▓рдгрд╛рд░реЗ рдЯреЗрдмрд▓ рд╕рд╛рдл рдХрд░рд╛ рд▓рд╛рдВрдм рдкреНрд░рд╢реНрдирд╛рдВрдиреА рд╡реЗрдврд▓реЗрд▓реЗ рдЖрдгрд┐ рджрдВрддрд╛рд│реЗрд╡рд░ рдкрд╛рдКрд▓ рдареЗрд╡рдд рдирд╛рд╣реА?

рдЬреЗрд╡реНрд╣рд╛ рд╡реНрд╣реЕрдХреНрдпреВрдо рдЕрдпрд╢рд╕реНрд╡реА рд╣реЛрддреЛ, рддреЗрд╡реНрд╣рд╛ рдЖрдореНрд╣реА рдЯреЗрдмрд▓ рд╕реНрд╡рд╣рд╕реНрддреЗ рд╕рд╛рдл рдХрд░рддреЛ

рджрдВрддрд╛рд│реЗ рдЙрд▓рдЧрдбрдгреЗ

рдкреНрд░рдердо, рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдХреЛрдгрддреА рд╕рдорд╕реНрдпрд╛ рд╕реЛрдбрд╡рд╛рдпрдЪреА рдЖрд╣реЗ рдЖрдгрд┐ рддреА рдХрд╢реА рдЙрджреНрднрд╡реВ рд╢рдХрддреЗ рд╣реЗ рдард░рд╡реВрдпрд╛.

рд╕рд╣рд╕рд╛ рд╣реА рдкрд░рд┐рд╕реНрдерд┐рддреА рдЙрджреНрднрд╡рддреЗ рддреБрд▓рдиреЗрдиреЗ рд▓рд╣рд╛рди рдЯреЗрдмрд▓рд╡рд░, рдкрд░рдВрддреБ рдЬреНрдпрд╛рдордзреНрдпреЗ рддреЗ рдЙрджреНрднрд╡рддреЗ рдмрд░реЗрдЪ рдмрджрд▓. рд╕рд╣рд╕рд╛ рд╣реЗ рдХрд┐рдВрд╡рд╛ рд╡реЗрдЧрд│реЗ рдореАрдЯрд░/рдПрдХреВрдг/рд░реЗрдЯрд┐рдВрдЧ, рдЬреНрдпрд╛рд╡рд░ рдЕрджреНрдпрддрди рдЕрдиреЗрдХрджрд╛ рдХреЗрд▓реЗ рдЬрд╛рддреЗ, рдХрд┐рдВрд╡рд╛ рдмрдлрд░ рд░рд╛рдВрдЧ рдХрд╛рд╣реА рд╕рддрдд рдЪрд╛рд▓реВ рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдЗрд╡реНрд╣реЗрдВрдЯреНрд╕рд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рдЬреНрдпрд╛рдЪреЗ рд░реЗрдХреЙрд░реНрдб рд╕рддрдд 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

рдЕрд░реЗ, рд╕рд╛рдл рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдХрд╛рд╣реАрд╣реА рдирд╛рд╣реА! рд╕рдорд╛рдВрддрд░ рдЪрд╛рд▓реВ рд╡рд┐рдирдВрддреА рдЖрдордЪреНрдпрд╛рдд рд╣рд╕реНрддрдХреНрд╖реЗрдк рдХрд░рдд рдЖрд╣реЗ - рд╢реЗрд╡рдЯреА, рддреНрдпрд╛рд▓рд╛ рдХрдзреАрддрд░реА рдпрд╛ рдЖрд╡реГрддреНрддреНрдпрд╛рдВрдХрдбреЗ рд╡рд│рд╛рдпрдЪреЗ рдЕрд╕реЗрд▓ (рдХрд╛рдп рдЕрд╕реЗрд▓ рддрд░?), рдЖрдгрд┐ рддреЗ рддреНрдпрд╛рдЪреНрдпрд╛рд╕рд╛рдареА рдЙрдкрд▓рдмреНрдз рдЕрд╕рд▓реЗ рдкрд╛рд╣рд┐рдЬреЗрдд. рдЖрдгрд┐ рдореНрд╣рдгреВрдирдЪ рд╡реНрд╣реЕрдХреНрдпреВрдо рдлреБрд▓ рджреЗрдЦреАрд▓ рдЖрдореНрд╣рд╛рд▓рд╛ рдорджрдд рдХрд░рдгрд╛рд░ рдирд╛рд╣реА.

рдЯреЗрдмрд▓ "рдХреЛрд╕рд│рдд рдЖрд╣реЗ".

рдкрдг рдЖрдореНрд╣рд╛рд▓рд╛ рдЦрд╛рддреНрд░реА рдЖрд╣реЗ рдХреА рддреНрдпрд╛ рдХреНрд╡реЗрд░реАрд▓рд╛ рдЖрдордЪреНрдпрд╛ рдЯреЗрдмрд▓рдЪреА рдЧрд░рдЬ рдирд╛рд╣реА. рдореНрд╣рдгреВрди, рдЖрдореНрд╣реА рдЕрдЬреВрдирд╣реА рдЯреЗрдмрд▓рдордзреВрди рдЕрдирд╛рд╡рд╢реНрдпрдХ рд╕рд░реНрд╡рдХрд╛рд╣реА рдХрд╛рдвреВрди рдЯрд╛рдХреВрди рд╕рд┐рд╕реНрдЯрдо рдХрд╛рд░реНрдпрдкреНрд░рджрд░реНрд╢рди рдкреБрд░реЗрд╢рд╛ рдорд░реНрдпрд╛рджреЗрдкрд░реНрдпрдВрдд рдкрд░рдд рдХрд░рдгреНрдпрд╛рдЪрд╛ рдкреНрд░рдпрддреНрди рдХрд░реВ - рдХрдореАрддрдХрдореА "рдореЕрдиреНрдпреБрдЕрд▓реА", рдХрд╛рд░рдг рд╡реНрд╣реЕрдХреНрдпреВрдо рд╕реЛрдбреВрди рджреЗрддреЛ.

рд╣реЗ рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рдмрдлрд░ рдЯреЗрдмрд▓рдЪреНрдпрд╛ рдХреЗрд╕рдЪреЗ рдЙрджрд╛рд╣рд░рдг рдкрд╛рд╣реВ. рдореНрд╣рдгрдЬреЗрдЪ, INSERT/DELETE рдЪрд╛ рдореЛрдард╛ рдкреНрд░рд╡рд╛рд╣ рдЕрд╕рддреЛ рдЖрдгрд┐ рдХрд╛рд╣реАрд╡реЗрд│рд╛ рдЯреЗрдмрд▓ рдкреВрд░реНрдгрдкрдгреЗ рд░рд┐рдХрд╛рдореЗ рдЕрд╕рддреЗ. рдкрд░рдВрддреБ рдЬрд░ рддреЗ рд░рд┐рдХрд╛рдореЗ рдирд╕реЗрд▓, рддрд░ рдЖрдкрдг рддреЗ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ рддреНрдпрд╛рдЪреА рд╡рд░реНрддрдорд╛рди рд╕рд╛рдордЧреНрд░реА рдЬрддрди рдХрд░рд╛.

#0: рдкрд░рд┐рд╕реНрдерд┐рддреАрдЪреЗ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░рдгреЗ

рд╣реЗ рд╕реНрдкрд╖реНрдЯ рдЖрд╣реЗ рдХреА рдкреНрд░рддреНрдпреЗрдХ рдСрдкрд░реЗрд╢рдирдирдВрддрд░рд╣реА рдЖрдкрдг рдЯреЗрдмрд▓рд╕рд╣ рдХрд╛рд╣реАрддрд░реА рдХрд░рдгреНрдпрд╛рдЪрд╛ рдкреНрд░рдпрддреНрди рдХрд░реВ рд╢рдХрддрд╛, рдкрд░рдВрддреБ рдпрд╛рдЪрд╛ рдлрд╛рд░рд╕рд╛ рдЕрд░реНрде рдирд╛рд╣реА - рджреЗрдЦрднрд╛рд▓ рдУрд╡реНрд╣рд░рд╣реЗрдб рд╕реНрдкрд╖реНрдЯрдкрдгреЗ рд▓рдХреНрд╖реНрдп рдХреНрд╡реЗрд░реАрдЪреНрдпрд╛ рдереНрд░реВрдкреБрдЯрдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд рдЕрд╕реЗрд▓.

рдЪрд▓рд╛ рдирд┐рдХрд╖ рддрдпрд╛рд░ рдХрд░реВ - "рдХрд╛рд░реНрдп рдХрд░рдгреНрдпрд╛рдЪреА рд╡реЗрд│ рдЖрд▓реА рдЖрд╣реЗ" рдЬрд░:

  • рд╡реНрд╣реЕрдХреНрдпреВрдо рдЦреВрдк рдкреВрд░реНрд╡реА рд▓реЙрдиреНрдЪ рдХреЗрд▓реЗ рдЧреЗрд▓реЗ рд╣реЛрддреЗ
    рдЖрдореНрд╣рд╛рд▓рд╛ рднрд╛рд░реА рднрд╛рд░ рдЕрдкреЗрдХреНрд╖рд┐рдд рдЖрд╣реЗ, рдореНрд╣рдгреВрди рддреЗ рд╣реЛрдК рджреНрдпрд╛ 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: рдЕрдЬреВрдирд╣реА рд╡реНрд╣реЕрдХреНрдпреВрдо

рд╕рдорд╛рдВрддрд░ рдХреНрд╡реЗрд░реА рдЖрдкрд▓реНрдпрд╛рдордзреНрдпреЗ рд▓рдХреНрд╖рдгреАрдп рд╣рд╕реНрддрдХреНрд╖реЗрдк рдХрд░рдд рдЖрд╣реЗ рдХреА рдирд╛рд╣реА рд╣реЗ рдЖрдореНрд╣рд╛рд▓рд╛ рдЖрдзреАрдЪ рдХрд│реВ рд╢рдХрдд рдирд╛рд╣реА - рддреЗ рд╕реБрд░реВ рдЭрд╛рд▓реНрдпрд╛рдкрд╛рд╕реВрди рдиреЗрдордХреЗ рдХрд┐рддреА рд░реЗрдХреЙрд░реНрдб "рдХрд╛рд▓рдмрд╛рд╣реНрдп" рдЭрд╛рд▓реЗ рдЖрд╣реЗрдд. рдореНрд╣рдгреВрди, рдЬреЗрд╡реНрд╣рд╛ рдЖрдкрдг рдЯреЗрдмрд▓рд╡рд░ рдХрд╕рд╛ рддрд░реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рдгреНрдпрд╛рдЪрд╛ рдирд┐рд░реНрдгрдп рдШреЗрддреЛ, рдХреЛрдгрддреНрдпрд╛рд╣реА рдкрд░рд┐рд╕реНрдерд┐рддреАрдд, рдЖрдкрдг рдкреНрд░рдердо рддреНрдпрд╛рд╡рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХреЗрд▓реЗ рдкрд╛рд╣рд┐рдЬреЗ рдкреЛрдХрд│реА - рд╡реНрд╣реЕрдХреНрдпреВрдо рдлреБрд▓рдЪреНрдпрд╛ рд╡рд┐рдкрд░реАрдд, рддреЗ рд╡рд╛рдЪрди-рд▓реЗрдЦрди рдбреЗрдЯрд╛рд╕рд╣ рдХрд╛рд░реНрдп рдХрд░рдгрд╛рд░реНтАНрдпрд╛ рд╕рдорд╛рдВрддрд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдВрдордзреНрдпреЗ рд╡реНрдпрддреНрдпрдп рдЖрдгрдд рдирд╛рд╣реА.

рддреНрдпрд╛рдЪ рд╡реЗрд│реА, рдЖрдореНрд╣реА рдЬреЗ рдХрд╛рд╣реА рдХрд╛рдвреВ рдЗрдЪреНрдЫрд┐рддреЛ рддреЗ рддреЗ рддреНрд╡рд░рд┐рдд рд╕рд╛рдл рдХрд░реВ рд╢рдХрддреЗ. рд╣реЛрдп, рдЖрдгрд┐ рдпрд╛ рдЯреЗрдмрд▓рд╡рд░реАрд▓ рддреНрдпрд╛рдирдВрддрд░рдЪреНрдпрд╛ рдХреНрд╡реЗрд░реА рдЖрдордЪреНрдпрд╛рдХрдбреЗ рдЬрд╛рддреАрд▓ "рд╣реЙрдЯ рдХреЕрд╢реЗ" рджреНрд╡рд╛рд░реЗ, рдЬреНрдпрд╛рдореБрд│реЗ рддреНрдпрд╛рдВрдЪрд╛ рдХрд╛рд▓рд╛рд╡рдзреА рдХрдореА рд╣реЛрдИрд▓ - рдЖрдгрд┐ рдореНрд╣рдгреВрди, рдЖрдордЪреНрдпрд╛ рд╕рд░реНрд╡реНрд╣рд┐рд╕рд┐рдВрдЧ рд╡реНрдпрд╡рд╣рд╛рд░рд╛рджреНрд╡рд╛рд░реЗ рдЗрддрд░рд╛рдВрдирд╛ рдмреНрд▓реЙрдХ рдХрд░рдгреНрдпрд╛рдЪрд╛ рдПрдХреВрдг рд╡реЗрд│.

#2: рдШрд░реА рдХреЛрдгреА рдЖрд╣реЗ рдХрд╛?

рдЯреЗрдмрд▓рдордзреНрдпреЗ рдХрд╛рд╣реА рдЖрд╣реЗ рдХрд╛ рддреЗ рддрдкрд╛рд╕реВрдпрд╛:

TABLE tbl LIMIT 1;

рдЬрд░ рдПрдХрд╣реА рд░реЗрдХреЙрд░реНрдб рд╢рд┐рд▓реНрд▓рдХ рдирд╕реЗрд▓, рддрд░ рдЖрдкрдг рдлрдХреНрдд рдЪрд╛рд▓рд╡реВрди рдкреНрд░рдХреНрд░рд┐рдпреЗрд╡рд░ рдЦреВрдк рдмрдЪрдд рдХрд░реВ рд╢рдХрддреЛ рдЯреНрд░рдВрдХ рдХрд░рд╛:

рд╣реЗ рдкреНрд░рддреНрдпреЗрдХ рдЯреЗрдмрд▓рд╕рд╛рдареА рдмрд┐рдирд╢рд░реНрдд DELETE рдХрдорд╛рдВрдб рдкреНрд░рдорд╛рдгреЗрдЪ рдХрд╛рд░реНрдп рдХрд░рддреЗ, рдкрд░рдВрддреБ рддреЗ рдЯреЗрдмрд▓ рд╕реНрдХреЕрди рдХрд░рдд рдирд╕рд▓реНрдпрд╛рдореБрд│реЗ рддреЗ рдЦреВрдк рд╡реЗрдЧрд╡рд╛рди рдЖрд╣реЗ. рд╢рд┐рд╡рд╛рдп, рддреЗ рддрд╛рдмрдбрддреЛрдм рдбрд┐рд╕реНрдХ рдЬрд╛рдЧрд╛ рдореЛрдХрд│реА рдХрд░рддреЗ, рддреНрдпрд╛рдореБрд│реЗ рдирдВрддрд░ рд╡реНрд╣реЕрдХреНрдпреВрдо рдСрдкрд░реЗрд╢рди рдХрд░рдгреНрдпрд╛рдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╛рд╣реА.

рддреБрдореНрд╣рд╛рд▓рд╛ рдЯреЗрдмрд▓ рд╕рд┐рдХреНрд╡реЗрдиреНрд╕ рдХрд╛рдЙрдВрдЯрд░ (рд░реАрд╕реНрдЯрд╛рд░реНрдЯ рдЖрдпрдбреЗрдВрдЯрд┐рдЯреА) рд░реАрд╕реЗрдЯ рдХрд░рд╛рдпрдЪрд╛ рдЖрд╣реЗ рдХреА рдирд╛рд╣реА рд╣реЗ рддреБрдореНрд╣реА рдард░рд╡реВ рд╢рдХрддрд╛.

#3: рдкреНрд░рддреНрдпреЗрдХрдЬрдг - рд╡рд│рдг рдШреНрдпрд╛!

рдЖрдореНрд╣реА рдЕрддреНрдпрдВрдд рд╕реНрдкрд░реНрдзрд╛рддреНрдордХ рд╡рд╛рддрд╛рд╡рд░рдгрд╛рдд рдХрд╛рдо рдХрд░рдд рдЕрд╕рд▓реНрдпрд╛рдиреЗ, рдЖрдореНрд╣реА рдпреЗрдереЗ рдЯреЗрдмрд▓рдордзреНрдпреЗ рдХреЛрдгрддреНрдпрд╛рд╣реА рдиреЛрдВрджреА рдирд╛рд╣реАрдд рд╣реЗ рддрдкрд╛рд╕рдд рдЕрд╕рддрд╛рдирд╛, рдХреЛрдгреАрддрд░реА рдЖрдзреАрдЪ рддреЗрдереЗ рдХрд╛рд╣реАрддрд░реА рд▓рд┐рд╣рд┐рд▓реЗ рдЕрд╕реЗрд▓. рдЖрдореНрд╣реА рд╣реА рдорд╛рд╣рд┐рддреА рдЧрдорд╛рд╡реВ рдирдпреЗ, рдордЧ рдХрд╛рдп? рд╣реЗ рдмрд░реЛрдмрд░ рдЖрд╣реЗ, рдЖрдореНрд╣реА рд╣реЗ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ рдХреА рдХреЛрдгреАрд╣реА рддреЗ рдирд┐рд╢реНрдЪрд┐рддрдкрдгреЗ рд▓рд┐рд╣реВ рд╢рдХрдд рдирд╛рд╣реА.

рд╣реЗ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдореНрд╣рд╛рд▓рд╛ рд╕рдХреНрд╖рдо рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ рдорд╛рд▓рд┐рдХрд╛ рдХрд░рдгреНрдпрд╛рдпреЛрдЧреНрдп-рдЖрдордЪреНрдпрд╛ рд╡реНрдпрд╡рд╣рд╛рд░рд╛рд╕рд╛рдареА рдЕрд▓рдЧрд╛рд╡ (рд╣реЛрдп, рдпреЗрдереЗ рдЖрдореНрд╣реА рд╡реНрдпрд╡рд╣рд╛рд░ рд╕реБрд░реВ рдХрд░рддреЛ) рдЖрдгрд┐ рдЯреЗрдмрд▓рд▓рд╛ тАЬрдШрдЯреНрдЯтАЭ рд▓реЙрдХ рдХрд░рд╛:

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

рдмреНрд▓реЙрдХрд┐рдВрдЧрдЪреА рд╣реА рдкрд╛рддрд│реА рдЖрдореНрд╣реА рддреНрдпрд╛рд╡рд░ рдХрд░реВ рдЗрдЪреНрдЫрд┐рдд рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдСрдкрд░реЗрд╢рдиреНрд╕рджреНрд╡рд╛рд░реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреЗрд▓реА рдЬрд╛рддреЗ.

#4: рд╕реНрд╡рд╛рд░рд╕реНрдпрд╛рдВрдЪрд╛ рд╕рдВрдШрд░реНрд╖

рдЖрдореНрд╣реА рдпреЗрдереЗ рдЖрд▓реЛ рдЖрдгрд┐ рдЪрд┐рдиреНрд╣ "рд▓реЙрдХ" рдХрд░реВ рдЗрдЪреНрдЫрд┐рддреЛ - рдЬрд░ рддреНрдпрд╛ рдХреНрд╖рдгреА рдХреЛрдгреАрддрд░реА рддреНрдпрд╛рд╡рд░ рд╕рдХреНрд░рд┐рдп рдЕрд╕реЗрд▓ рддрд░, рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рддреНрдпрд╛рддреВрди рд╡рд╛рдЪрдгреЗ? рд╣рд╛ рдмреНрд▓реЙрдХ рд░рд┐рд▓реАрдЭ рд╣реЛрдгреНрдпрд╛рдЪреА рд╡рд╛рдЯ рдкрд╛рд╣рдд рдЖрдореНрд╣реА "рд╣рдБрдЧ" рдХрд░реВ, рдЖрдгрд┐ рдЗрддрд░ рдЬреНрдпрд╛рдВрдирд╛ рд╡рд╛рдЪрд╛рдпрдЪреЗ рдЖрд╣реЗ рддреЗ рдЖрдордЪреНрдпрд╛рдХрдбреЗ рдзрд╛рд╡рддреАрд▓...

рд╣реЗ рд╣реЛрдгреНрдпрд╛рдкрд╛рд╕реВрди рд░реЛрдЦрдгреНрдпрд╛рд╕рд╛рдареА, рдЖрдореНрд╣реА "рд╕реНрд╡рддрдГрдЪрд╛ рддреНрдпрд╛рдЧ" рдХрд░реВ - рдЬрд░ рдЖрдореНрд╣реА рдард░рд╛рд╡рд┐рдХ (рд╕реНрд╡реАрдХрд╛рд░рдгреНрдпрд╛рдпреЛрдЧреНрдпрдкрдгреЗ рдХрдореА) рд╡реЗрд│реЗрдд рд▓реЙрдХ рдорд┐рд│рд╡реВ рд╢рдХрд▓реЛ рдирд╛рд╣реА, рддрд░ рдЖрдореНрд╣рд╛рд▓рд╛ рдмреЗрд╕рдХрдбреВрди рдЕрдкрд╡рд╛рдж рдорд┐рд│реЗрд▓, рдкрд░рдВрддреБ рдХрдореАрддрдХрдореА рдЖрдореНрд╣реА рддреНрдпрд╛рдд рдЬрд╛рд╕реНрдд рд╣рд╕реНрддрдХреНрд╖реЗрдк рдХрд░рдгрд╛рд░ рдирд╛рд╣реА. рдЗрддрд░.

рд╣реЗ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рд╕рддреНрд░ рд╡реНрд╣реЗрд░рд┐рдПрдмрд▓ рд╕реЗрдЯ рдХрд░рд╛ рд▓реЙрдХ_рдЯрд╛рдЗрдордЖрдЙрдЯ (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

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛