Π Π΅ΡΠ»ΠΈ ΡΠ°ΠΊΠΎΠΉ Π½Π΅ΠΏΡΠΈΡΡΠ½ΡΠΉ ΡΠΈΠΏ (ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠΈΡΠ΅Π»ΡΠ½Π°Ρ OLAP-Π½Π°Π³ΡΡΠ·ΠΊΠ° Π½Π° OLTP-Π±Π°Π·Π΅) Π²ΡΠ΅ ΠΆΠ΅ Π΅ΡΡΡ? ΠΠ°ΠΊ ΠΏΠΎΡΠΈΡΡΠΈΡΡ Π°ΠΊΡΠΈΠ²Π½ΠΎ ΠΌΠ΅Π½ΡΡΡΡΡΡΡ ΡΠ°Π±Π»ΠΈΡΡ Π² ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΠΈ Π΄Π»ΠΈΠ½Π½ΡΡ Π·Π°ΠΏΡΠΎΡΠΎΠ² ΠΈ Π½Π΅ Π½Π°ΡΡΡΠΏΠΈΡΡ Π½Π° Π³ΡΠ°Π±Π»ΠΈ?
Π Π°ΡΠΊΠ»Π°Π΄ΡΠ²Π°Π΅ΠΌ Π³ΡΠ°Π±Π»ΠΈ
Π‘Π½Π°ΡΠ°Π»Π° ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΠΌ, Π² ΡΠ΅ΠΌ ΠΆΠ΅ Π·Π°ΠΊΠ»ΡΡΠ°Π΅ΡΡΡ ΠΈ ΠΊΠ°ΠΊ Π²ΠΎΠΎΠ±ΡΠ΅ ΠΌΠΎΠΆΠ΅Ρ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ°, ΠΊΠΎΡΠΎΡΡΡ ΠΌΡ Ρ ΠΎΡΠΈΠΌ ΡΠ΅ΡΠΈΡΡ.
ΠΠ±ΡΡΠ½ΠΎ ΡΠ°ΠΊΠ°Ρ ΡΠΈΡΡΠ°ΡΠΈΡ ΡΠ»ΡΡΠ°Π΅ΡΡΡ Π½Π° ΠΎΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½ΠΎ Π½Π΅Π±ΠΎΠ»ΡΡΠΎΠΉ ΡΠ°Π±Π»ΠΈΡΠ΅, Π½ΠΎ Π² ΠΊΠΎΡΠΎΡΠΎΠΉ ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΠΈΡ ΠΎΡΠ΅Π½Ρ ΠΌΠ½ΠΎΠ³ΠΎ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ. ΠΠ±ΡΡΠ½ΠΎ ΡΡΠΎ ΠΈΠ»ΠΈ ΡΠ°Π·Π½ΡΠ΅ ΡΡΠ΅ΡΡΠΈΠΊΠΈ/Π°Π³ΡΠ΅Π³Π°ΡΡ/ΡΠ΅ΠΉΡΠΈΠ½Π³ΠΈ, Π½Π° ΠΊΠΎΡΠΎΡΡΡ ΡΠ°ΡΡΠΎ-ΡΠ°ΡΡΠΎ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ UPDATE, ΠΈΠ»ΠΈ Π±ΡΡΠ΅Ρ-ΠΎΡΠ΅ΡΠ΅Π΄Ρ Π΄Π»Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ ΠΊΠ°ΠΊΠΎΠ³ΠΎ-ΡΠΎ ΠΏΠΎΡΡΠΎΡΠ½Π½ΠΎ ΠΈΠ΄ΡΡΠ΅Π³ΠΎ ΠΏΠΎΡΠΎΠΊΠ° ΡΠΎΠ±ΡΡΠΈΠΉ, Π·Π°ΠΏΠΈΡΠΈ ΠΎ ΠΊΠΎΡΠΎΡΡΡ Π²ΡΠ΅ Π²ΡΠ΅ΠΌΡ 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);
Π’Π΅ΠΏΠ΅ΡΡ ΠΌΡ ΠΌΠ½ΠΎΠ³ΠΎ-ΠΌΠ½ΠΎΠ³ΠΎ ΡΠ°Π· ΠΎΠ±Π½ΠΎΠ²Π»ΡΠ΅ΠΌ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ· ΡΡΠ΅ΡΡΠΈΠΊΠΎΠ². ΠΠ»Ρ ΡΠΈΡΡΠΎΡΡ ΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½ΡΠ° ΡΠ΄Π΅Π»Π°Π΅ΠΌ ΡΡΠΎ
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
Π§ΡΠΎ ΠΆΠ΅ ΠΏΡΠΎΠΈΠ·ΠΎΡΠ»ΠΎ? ΠΠΎΡΠ΅ΠΌΡ Π΄Π°ΠΆΠ΅ Π΄Π»Ρ ΠΏΡΠΎΡΡΠ΅ΠΉΡΠ΅Π³ΠΎ UPDATE Π΅Π΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½ΠΎΠΉ Π·Π°ΠΏΠΈΡΠΈ Π²ΡΠ΅ΠΌΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π΄Π΅Π³ΡΠ°Π΄ΠΈΡΠΎΠ²Π°Π»ΠΎ Π² 7 ΡΠ°Π· β Ρ 0.524ms Π΄ΠΎ 3.808ms? ΠΠ° ΠΈ ΡΠ΅ΠΉΡΠΈΠ½Π³ Π½Π°Ρ ΡΡΡΠΎΠΈΡΡΡ Π²ΡΠ΅ ΠΌΠ΅Π΄Π»Π΅Π½Π½Π΅Π΅ ΠΈ ΠΌΠ΅Π΄Π»Π΅Π½Π½Π΅Π΅.
ΠΠΎ Π²ΡΠ΅ΠΌ Π²ΠΈΠ½ΠΎΠ²Π°Ρ 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 FULL Π½Π°ΠΌ Π½Π΅ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ.
Β«Π‘Ρ Π»Π°ΠΏΡΠ²Π°Π΅ΠΌΒ» ΡΠ°Π±Π»ΠΈΡΡ
ΠΠΎ ΠΌΡ-ΡΠΎ ΡΠΎΡΠ½ΠΎ Π·Π½Π°Π΅ΠΌ, ΡΡΠΎ ΡΠΎΠΌΡ Π·Π°ΠΏΡΠΎΡΡ Π½Π°ΡΠ° ΡΠ°Π±Π»ΠΈΡΠ° Π½Π΅ Π½ΡΠΆΠ½Π°. ΠΠΎΡΡΠΎΠΌΡ ΠΏΠΎΠΏΡΠΎΠ±ΡΠ΅ΠΌ Π²ΡΠ΅-ΡΠ°ΠΊΠΈ Π²Π΅ΡΠ½ΡΡΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡ ΡΠΈΡΡΠ΅ΠΌΡ Π² Π°Π΄Π΅ΠΊΠ²Π°ΡΠ½ΡΠ΅ ΡΠ°ΠΌΠΊΠΈ, Π²ΡΠΊΠΈΠ½ΡΠ² ΠΈΠ· ΡΠ°Π±Π»ΠΈΡΡ Π²ΡΠ΅ Π»ΠΈΡΠ½Π΅Π΅ β Ρ ΠΎΡΡ Π±Ρ ΠΈ Β«Π²ΡΡΡΠ½ΡΡΒ», ΡΠ°Π· VACUUM ΠΏΠ°ΡΡΠ΅Ρ.
Π§ΡΠΎΠ±Ρ Π±ΡΠ»ΠΎ Π½Π°Π³Π»ΡΠ΄Π½Π΅Π΅, ΡΠ°ΡΡΠΌΠΎΡΡΠΈΠΌ ΡΠΆΠ΅ Π½Π° ΠΏΡΠΈΠΌΠ΅ΡΠ΅ ΡΠ»ΡΡΠ°Ρ ΡΠ°Π±Π»ΠΈΡΡ-Π±ΡΡΠ΅ΡΠ°. Π’ΠΎ Π΅ΡΡΡ ΠΈΠ΄Π΅Ρ Π±ΠΎΠ»ΡΡΠΎΠΉ ΠΏΠΎΡΠΎΠΊ INSERT/DELETE, ΠΈ ΠΈΠ½ΠΎΠ³Π΄Π° Π² ΡΠ°Π±Π»ΠΈΡΠ΅ ΠΎΠΊΠ°Π·ΡΠ²Π°Π΅ΡΡΡ Π²ΠΎΠΎΠ±ΡΠ΅ ΠΏΡΡΡΠΎ. ΠΠΎ Π΅ΡΠ»ΠΈ ΡΠ°ΠΌ Π½Π΅ ΠΏΡΡΡΠΎ, ΠΌΡ Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠΎΡ ΡΠ°Π½ΠΈΡΡ Π΅Π΅ ΡΠ΅ΠΊΡΡΠ΅Π΅ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ΅.
#0: ΠΡΠ΅Π½ΠΈΠ²Π°Π΅ΠΌ ΡΠΈΡΡΠ°ΡΠΈΡ
ΠΠΎΠ½ΡΡΠ½ΠΎ, ΡΡΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡΡΠ°ΡΡΡΡ ΡΡΠΎ-ΡΠΎ Π΄Π΅Π»Π°ΡΡ Ρ ΡΠ°Π±Π»ΠΈΡΠ΅ΠΉ Ρ ΠΎΡΡ ΠΏΠΎΡΠ»Π΅ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ, Π½ΠΎ Π±ΠΎΠ»ΡΡΠΎΠ³ΠΎ ΡΠΌΡΡΠ»Π° ΡΡΠΎ Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ β Π½Π°ΠΊΠ»Π°Π΄Π½ΡΠ΅ ΡΠ°ΡΡ ΠΎΠ΄Ρ Π½Π° ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°Π½ΠΈΠ΅ Π±ΡΠ΄ΡΡ ΡΠ²Π½ΠΎ Π±ΠΎΠ»ΡΡΠ΅, ΡΠ΅ΠΌ ΠΏΡΠΎΠΏΡΡΠΊΠ½Π°Ρ ΡΠΏΠΎΡΠΎΠ±Π½ΠΎΡΡΡ ΡΠ΅Π»Π΅Π²ΡΡ Π·Π°ΠΏΡΠΎΡΠΎΠ².
Π‘ΡΠΎΡΠΌΡΠ»ΠΈΡΡΠ΅ΠΌ ΠΊΡΠΈΡΠ΅ΡΠΈΠΈ β Β«ΡΠΆΠ΅ ΠΏΠΎΡΠ° Π΄Π΅ΠΉΡΡΠ²ΠΎΠ²Π°ΡΡΒ», Π΅ΡΠ»ΠΈ:
- VACUUM Π·Π°ΠΏΡΡΠΊΠ°Π»ΡΡ Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ Π΄Π°Π²Π½ΠΎ
ΠΠ°Π³ΡΡΠ·ΠΊΡ ΠΎΠΆΠΈΠ΄Π°Π΅ΠΌ Π±ΠΎΠ»ΡΡΡΡ, ΠΏΠΎΡΡΠΎΠΌΡ ΠΏΡΡΡΡ ΡΡΠΎ Π±ΡΠ΄Π΅Ρ 60 ΡΠ΅ΠΊΡΠ½Π΄ Ρ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π³ΠΎ [auto]VACUUM. - ΡΠΈΠ·ΠΈΡΠ΅ΡΠΊΠΈΠΉ ΡΠ°Π·ΠΌΠ΅Ρ ΡΠ°Π±Π»ΠΈΡΡ Π±ΠΎΠ»ΡΡΠ΅ ΡΠ΅Π»Π΅Π²ΠΎΠ³ΠΎ
ΠΠΏΡΠ΅Π΄Π΅Π»ΠΈΠΌ Π΅Π³ΠΎ ΠΊΠ°ΠΊ ΡΠ΄Π²ΠΎΠ΅Π½Π½ΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΡΡΠ°Π½ΠΈΡ (Π±Π»ΠΎΠΊΠΎΠ² ΠΏΠΎ 8KB) ΠΎΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΡΠ°Π·ΠΌΠ΅ΡΠ° β 1 blk Π½Π° heap + 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
ΠΡ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π½Π°ΡΡ Π·Π°ΡΠ°Π½Π΅Π΅, ΡΠΈΠ»ΡΠ½ΠΎ Π»ΠΈ Π½Π°ΠΌ ΠΌΠ΅ΡΠ°Π΅Ρ ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΡΠΉ Π·Π°ΠΏΡΠΎΡ β ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΈΠΌΠ΅Π½Π½ΠΎ Π·Π°ΠΏΠΈΡΠ΅ΠΉ Β«ΡΡΡΠ°ΡΠ΅Π»ΠΎΒ» Ρ ΠΌΠΎΠΌΠ΅Π½ΡΠ° Π΅Π³ΠΎ Π½Π°ΡΠ°Π»Π°. ΠΠΎΡΡΠΎΠΌΡ, ΠΊΠΎΠ³Π΄Π° Π²ΡΠ΅-ΡΠ°ΠΊΠΈ ΡΠ΅ΡΠΈΠΌ ΡΠ°Π±Π»ΠΈΡΡ ΠΊΠ°ΠΊ-ΡΠΎ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°ΡΡ, ΠΏΠΎ-Π»ΡΠ±ΠΎΠΌΡ ΡΠ½Π°ΡΠ°Π»Π° ΡΡΠΎΠΈΡ Π²ΡΠΏΠΎΠ»Π½ΠΈΡΡ Π½Π° Π½Π΅ΠΉ VACUUM β ΠΎΠ½, Π² ΠΎΡΠ»ΠΈΡΠΈΠ΅ ΠΎΡ VACUUM FULL, ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΡΠΌ ΠΏΡΠΎΡΠ΅ΡΡΠ°ΠΌ ΡΠ°Π±ΠΎΡΠ°ΡΡ Ρ Π΄Π°Π½Π½ΡΠΌΠΈ Π½Π° ΡΡΠ΅Π½ΠΈΠ΅-Π·Π°ΠΏΠΈΡΡ Π½Π΅ ΠΌΠ΅ΡΠ°Π΅Ρ.
ΠΠ°ΠΎΠ΄Π½ΠΎ ΠΎΠ½ ΠΌΠΎΠΆΠ΅Ρ ΡΡΠ°Π·Ρ Π²ΡΡΠΈΡΡΠΈΡΡ Π±ΠΎΠ»ΡΡΡΡ ΡΠ°ΡΡΡ ΡΠΎΠ³ΠΎ, ΡΡΠΎ ΠΌΡ Ρ ΠΎΡΠ΅Π»ΠΈ Π±Ρ ΡΠ±ΡΠ°ΡΡ. ΠΠ° ΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΡΡΡΠΈΠ΅ Π·Π°ΠΏΡΠΎΡΡ ΠΏΠΎ ΡΡΠΎΠΉ ΡΠ°Π±Π»ΠΈΡΠ΅ ΠΏΠΎΠΉΠ΄ΡΡ Ρ Π½Π°Ρ ΠΏΠΎ Β«Π³ΠΎΡΡΡΠ΅ΠΌΡ ΠΊΡΡΡΒ», ΡΡΠΎ ΡΠΎΠΊΡΠ°ΡΠΈΡ ΠΈΡ ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡ β Π°, Π·Π½Π°ΡΠΈΡ, ΠΈ ΡΡΠΌΠΌΠ°ΡΠ½ΠΎΠ΅ Π²ΡΠ΅ΠΌΡ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ Π΄ΡΡΠ³ΠΈΡ Π½Π°ΡΠ΅ΠΉ ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°ΡΡΠ΅ΠΉ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠ΅ΠΉ.
#2: ΠΡΡΡ ΠΊΡΠΎ-Π½ΠΈΠ±ΡΠ΄Ρ Π΄ΠΎΠΌΠ°?
ΠΠ°Π²Π°ΠΉΡΠ΅ ΠΏΡΠΎΠ²Π΅ΡΠΈΠΌ β Π΅ΡΡΡ Π»ΠΈ Π² ΡΠ°Π±Π»ΠΈΡΠ΅ Π²ΠΎΠΎΠ±ΡΠ΅ Ρ ΠΎΡΡ ΡΡΠΎ-ΡΠΎ:
TABLE tbl LIMIT 1;
ΠΡΠ»ΠΈ Π½Π΅ ΠΎΡΡΠ°Π»ΠΎΡΡ Π½ΠΈ Π΅Π΄ΠΈΠ½ΠΎΠΉ Π·Π°ΠΏΠΈΡΠΈ, ΡΠΎ ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ ΡΠΈΠ»ΡΠ½ΠΎ ΡΡΠΊΠΎΠ½ΠΎΠΌΠΈΡΡ Π½Π° ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ΅ β ΠΏΡΠΎΡΡΠΎ Π²ΡΠΏΠΎΠ»Π½ΠΈΠ²
ΠΠ½Π° Π΄Π΅ΠΉΡΡΠ²ΡΠ΅Ρ ΡΠ°ΠΊ ΠΆΠ΅, ΠΊΠ°ΠΊ Π±Π΅Π·ΡΡΠ»ΠΎΠ²Π½Π°Ρ ΠΊΠΎΠΌΠ°Π½Π΄Π° DELETE Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΡΠ°Π±Π»ΠΈΡΡ, Π½ΠΎ Π³ΠΎΡΠ°Π·Π΄ΠΎ Π±ΡΡΡΡΠ΅Π΅, ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΠΎΠ½Π° ΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈ Π½Π΅ ΡΠΊΠ°Π½ΠΈΡΡΠ΅Ρ ΡΠ°Π±Π»ΠΈΡΡ. ΠΠΎΠ»Π΅Π΅ ΡΠΎΠ³ΠΎ, ΠΎΠ½Π° Π½Π΅ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎ Π²ΡΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π΅Ρ Π΄ΠΈΡΠΊΠΎΠ²ΠΎΠ΅ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²ΠΎ, ΡΠ°ΠΊ ΡΡΠΎ Π²ΡΠΏΠΎΠ»Π½ΡΡΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡ VACUUM ΠΏΠΎΡΠ»Π΅ Π½Π΅Ρ Π½Π΅ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ.
ΠΠ°Π΄ΠΎ Π»ΠΈ Π²Π°ΠΌ ΠΏΡΠΈ ΡΡΠΎΠΌ ΡΠ±ΡΠ°ΡΡΠ²Π°ΡΡ ΡΡΠ΅ΡΡΠΈΠΊ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ ΡΠ°Π±Π»ΠΈΡΡ (RESTART IDENTITY) β ΡΠ΅ΡΠ°ΠΉΡΠ΅ ΡΠ°ΠΌΠΈ.
#3: ΠΡΠ΅ β ΠΏΠΎ-ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ!
ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΌΡ ΡΠ°Π±ΠΎΡΠ°Π΅ΠΌ Π² ΡΡΠ»ΠΎΠ²ΠΈΡΡ Π²ΡΡΠΎΠΊΠΎΠΉ ΠΊΠΎΠ½ΠΊΡΡΠ΅Π½ΡΠ½ΠΎΡΡΠΈ, ΡΠΎ ΠΏΠΎΠΊΠ° ΠΌΡ ΡΡΡ ΠΏΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ ΠΎΡΡΡΡΡΡΠ²ΠΈΠ΅ Π·Π°ΠΏΠΈΡΠ΅ΠΉ Π² ΡΠ°Π±Π»ΠΈΡΠ΅, ΠΊΡΠΎ-ΡΠΎ ΠΌΠΎΠ³ ΡΡΠ΄Π° ΡΠΆΠ΅ ΡΡΠΎ-ΡΠΎ Π·Π°ΠΏΠΈΡΠ°ΡΡ. ΠΠΎΡΠ΅ΡΡΡΡ ΡΡΡ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΌΡ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ, Π·Π½Π°ΡΠΈΡ β ΡΡΠΎ? ΠΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎ, Π½Π°Π΄ΠΎ ΡΠ΄Π΅Π»Π°ΡΡ, ΡΡΠΎΠ±Ρ Π½ΠΈΠΊΡΠΎ ΡΠΆ ΡΠΎΡΠ½ΠΎ Π·Π°ΠΏΠΈΡΠ°ΡΡ Π½Π΅ ΠΌΠΎΠ³.
ΠΠ»Ρ ΡΡΠΎΠ³ΠΎ Π½Π°ΠΌ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ Π²ΠΊΠ»ΡΡΠΈΡΡ SERIALIZABLE-ΠΈΠ·ΠΎΠ»ΡΡΠΈΡ Π΄Π»Ρ Π½Π°ΡΠ΅ΠΉ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ (Π΄Π°, ΡΡΡ ΠΌΡ ΡΡΠ°ΡΡΡΠ΅ΠΌ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΡ) ΠΈ Π·Π°Π±Π»ΠΎΠΊΠΈΡΠΎΠ²Π°ΡΡ ΡΠ°Π±Π»ΠΈΡΡ Β«Π½Π°ΠΌΠ΅ΡΡΠ²ΠΎΒ»:
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
LOCK TABLE tbl IN ACCESS EXCLUSIVE MODE;
ΠΠΌΠ΅Π½Π½ΠΎ ΡΠ°ΠΊΠΎΠΉ ΡΡΠΎΠ²Π΅Π½Ρ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ ΠΎΠ±ΡΡΠ»ΠΎΠ²Π»Π΅Π½ ΡΠ΅ΠΌΠΈ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡΠΌΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΌΡ Ρ ΠΎΡΠΈΠΌ Π½Π°Π΄ Π½Π΅ΠΉ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΡ.
#4: ΠΠΎΠ½ΡΠ»ΠΈΠΊΡ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠΎΠ²
ΠΡ ΡΡΡ ΠΏΡΠΈΡ ΠΎΠ΄ΠΈΠΌ ΠΈ Ρ ΠΎΡΠΈΠΌ ΡΠ°Π±Π»ΠΈΡΠΊΡ Β«Π·Π°Π»ΠΎΡΠΈΡΡΒ» β Π° Π΅ΡΠ»ΠΈ Π½Π° Π½Π΅ΠΉ Π² ΡΡΠΎΡ ΠΌΠΎΠΌΠ΅Π½Ρ ΠΊΡΠΎ-ΡΠΎ Π±ΡΠ» Π°ΠΊΡΠΈΠ²Π΅Π½, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΡΠΈΡΠ°Π» ΠΈΠ· Π½Π΅Π΅? ΠΡ Β«ΠΏΠΎΠ²ΠΈΡΠ½Π΅ΠΌΒ» Π² ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠΈ ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π΅Π½ΠΈΡ ΡΡΠΎΠΉ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ, Π° Π΄ΡΡΠ³ΠΈΠ΅ ΠΆΠ΅Π»Π°ΡΡΠΈΠ΅ ΠΏΠΎΡΠΈΡΠ°ΡΡ ΡΠΏΡΡΡΡΡ ΡΠΆΠ΅ Π² Π½Π°Ρβ¦
Π§ΡΠΎΠ±Ρ ΡΠ°ΠΊΠΎΠ³ΠΎ Π½Π΅ ΠΏΡΠΎΠΈΠ·ΠΎΡΠ»ΠΎ, Β«ΠΏΠΎΠΆΠ΅ΡΡΠ²ΡΠ΅ΠΌ ΡΠΎΠ±ΠΎΠΉΒ» β Π΅ΡΠ»ΠΈ ΡΠΆ Π·Π° ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ΅ (Π΄ΠΎΠΏΡΡΡΠΈΠΌΠΎ ΠΌΠ°Π»ΠΎΠ΅) Π²ΡΠ΅ΠΌΡ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΡ Π½Π°ΠΌ ΠΏΠΎΠ»ΡΡΠΈΡΡ Π²ΡΠ΅-ΡΠ°ΠΊΠΈ Π½Π΅ ΡΠ΄Π°Π»ΠΎΡΡ, ΡΠΎ ΠΌΡ ΠΏΠΎΠ»ΡΡΠΈΠΌ ΠΎΡ Π±Π°Π·Ρ exception, Π½ΠΎ Ρ ΠΎΡΡ Π±Ρ Π½Π΅ ΠΏΠΎΠΌΠ΅ΡΠ°Π΅ΠΌ ΡΠΈΠ»ΡΠ½ΠΎ ΠΎΡΡΠ°Π»ΡΠ½ΡΠΌ.
ΠΠ»Ρ ΡΡΠΎΠ³ΠΎ Π²ΡΡΡΠ°Π²ΠΈΠΌ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΡΠ΅ΡΡΠΈΠΈ
SET statement_timeout = ...;LOCK TABLE ...;
Π§ΡΠΎΠ±Ρ Π½Π΅ Π·Π°Π½ΠΈΠΌΠ°ΡΡΡΡ ΠΏΠΎΡΠΎΠΌ Π²ΠΎΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ΠΌ Β«ΡΡΠ°ΡΠΎΠ³ΠΎΒ» Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ ΡΠΎΡΠΌΡ SET LOCAL, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΠ²Π°Π΅Ρ ΠΎΠ±Π»Π°ΡΡΡ Π΄Π΅ΠΉΡΡΠ²ΠΈΡ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ ΡΠ΅ΠΊΡΡΠ΅ΠΉ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠ΅ΠΉ.
ΠΠΎΠΌΠ½ΠΈΠΌ, ΡΡΠΎ statement_timeout ΡΠ°ΡΠΏΡΠΎΡΡΡΠ°Π½ΡΠ΅ΡΡΡ Π½Π° Π²ΡΠ΅ ΠΏΠΎΡΠ»Π΅Π΄ΡΡΡΠΈΠ΅ Π·Π°ΠΏΡΠΎΡΡ, ΡΡΠΎΠ±Ρ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΡ Π½Π΅ ΠΌΠΎΠ³Π»Π° Ρ Π½Π°Ρ ΡΠ°ΡΡΡΠ½ΡΡΡΡΡ Π΄ΠΎ Π½Π΅ΠΏΡΠΈΠ΅ΠΌΠ»Π΅ΠΌΡΡ Π²Π΅Π»ΠΈΡΠΈΠ½, Π΅ΡΠ»ΠΈ Π΄Π°Π½Π½ΡΡ Π² ΡΠ°Π±Π»ΠΈΡΠ΅ ΡΠ°ΠΊΠΈ ΠΎΠΊΠ°ΠΆΠ΅ΡΡΡ ΠΌΠ½ΠΎΠ³ΠΎ.
#5: ΠΠΎΠΏΠΈΡΡΠ΅ΠΌ Π΄Π°Π½Π½ΡΠ΅
ΠΡΠ»ΠΈ ΡΠ°Π±Π»ΠΈΡΠ° ΠΎΠΊΠ°Π·Π°Π»Π°ΡΡ Π½Π΅ ΡΠΎΠ²ΡΠ΅ΠΌ ΠΏΡΡΡΠ°Ρ β Π΄Π°Π½Π½ΡΠ΅ ΠΏΡΠΈΠ΄Π΅ΡΡΡ ΠΏΠ΅ΡΠ΅ΡΠΎΡ ΡΠ°Π½ΡΡΡ ΡΠ΅ΡΠ΅Π· Π²ΡΠΏΠΎΠΌΠΎΠ³Π°ΡΠ΅Π»ΡΠ½ΡΡ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΡΠ°Π±Π»ΠΈΡΠΊΡ:
CREATE TEMPORARY TABLE _tmp_swap ON COMMIT DROP AS TABLE tbl;
Π‘ΠΈΠ³Π½Π°ΡΡΡΠ° ON COMMIT DROP ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ, ΡΡΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ ΠΎΠΊΠΎΠ½ΡΠ°Π½ΠΈΡ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ Π²ΡΠ΅ΠΌΠ΅Π½Π½Π°Ρ ΡΠ°Π±Π»ΠΈΡΠ° ΠΏΠ΅ΡΠ΅ΡΡΠ°Π½Π΅Ρ ΡΡΡΠ΅ΡΡΠ²ΠΎΠ²Π°ΡΡ, ΠΈ Π·Π°Π½ΠΈΠΌΠ°ΡΡΡΡ Π΅Π΅ ΡΡΡΠ½ΡΠΌ ΡΠ΄Π°Π»Π΅Π½ΠΈΠ΅ΠΌ Π² ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ Π½Π΅ Π½ΡΠΆΠ½ΠΎ.
ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΌΡ ΠΏΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΠΌ, ΡΡΠΎ Β«ΠΆΠΈΠ²ΡΡ Β» Π΄Π°Π½Π½ΡΡ Π½Π΅ ΠΎΡΠ΅Π½Ρ ΠΌΠ½ΠΎΠ³ΠΎ, ΡΠΎ ΡΡΠ° ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡ Π΄ΠΎΠ»ΠΆΠ½Π° ΠΏΡΠΎΠΉΡΠΈ Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ Π±ΡΡΡΡΠΎ.
ΠΡ Π²ΠΎΡ ΠΊΠ°ΠΊ Π±Ρ ΠΈ Π²ΡΠ΅! ΠΠ΅ Π·Π°Π±ΡΠ²Π°ΠΉΡΠ΅ ΠΏΠΎΡΠ»Π΅ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΡ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ
Π‘ΠΎΠ±ΠΈΡΠ°Π΅ΠΌ ΠΈΡΠΎΠ³ΠΎΠ²ΡΠΉ ΡΠΊΡΠΈΠΏΡ
ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ ΡΠ°ΠΊΠΎΠΉ Β«ΠΏΡΠ΅Π²Π΄ΠΎΠΏΠΈΡΠΎΠ½Β»:
# ΡΠΎΠ±ΠΈΡΠ°Π΅ΠΌ ΡΡΠ°ΡΠΈΡΡΠΈΠΊΡ Ρ ΡΠ°Π±Π»ΠΈΡΡ
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 ΡΠ°ΠΌΠΎΠΉ ΡΠ°Π±Π»ΠΈΡΡ Π½Π΅ Π·Π°Π²ΡΠ·Π°Π½Ρ ΠΊΠ°ΠΊΠΈΠ΅-ΡΠΎ Π΄ΡΡΠ³ΠΈΠ΅ Π°ΠΊΡΠΈΠ²Π½ΠΎΡΡΠΈ ΡΠΎ ΡΡΠΎΡΠΎΠ½Ρ ΠΠ ΠΈΠ»ΠΈ 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 ΡΠ°Π·, ΠΈ Π²ΡΠ΅ UPDATE ΡΠ½ΠΎΠ²Π° Π±Π΅Π³Π°ΡΡ Π±ΡΡΡΡΠΎ.
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com