Я возился с VACUUM
и заметил некоторое неожиданное поведение, когда SELECT
извлечение строк из таблицы, кажется, сокращает объем работы, VACUUM
которую необходимо выполнить впоследствии.
Тестовые данные
Примечание: автовакуум отключен
CREATE TABLE numbers (num bigint);
ALTER TABLE numbers SET (
autovacuum_enabled = 'f',
toast.autovacuum_enabled = 'f'
);
INSERT INTO numbers SELECT generate_series(1, 5000);
Испытание 1
Теперь мы запускаем обновление для всех строк,
UPDATE numbers SET num = 0;
И когда мы бежим, VACUUM (VERBOSE) numbers;
мы получаем,
INFO: vacuuming "public.numbers"
INFO: "numbers": removed 5000 row versions in 23 pages
INFO: "numbers": found 5000 removable, 5000 nonremovable row versions in 45 out of 45 pages
DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 6585
There were 0 unused item pointers.
Испытание 2
Теперь мы выпускаем другой UPDATE
, но на этот раз мы добавим SELECT
потом,
UPDATE numbers SET num = 1;
SELECT * FROM numbers;
И когда мы бежим, VACUUM (VERBOSE) numbers;
мы получаем,
INFO: vacuuming "public.numbers"
INFO: "numbers": removed 56 row versions in 22 pages
INFO: "numbers": found 56 removable, 5000 nonremovable row versions in 45 out of 45 pages
DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 6586
There were 56 unused item pointers.
Что именно здесь происходит? Почему вторая версия, которую я запускаю, после SELECT
удаления мертвых кортежей со страниц, которые он посещает, совсем как VACUUM
делает?
Я использую Postgres 11.3 на macOS 10.14.5.
Ответы:
Из этого поста в / r / PostgreSQL к ответу Лоренца Альбе кажется, что ответственность за обновления могут вносить только Heap Only Tuples (HOT). Из описания горячих обновлений в
src/backend/access/heap/README.HOT
Цитата не в оригинальном ответе, но остальное цитата,
источник
CREATE INDEX idx_numbers ON numbers USING btree (num)
, VACUUM выход изменится наINFO: "numbers": removed 5000 row versions in 45 pages
. Однако обратите внимание, что в сценарии без индексаn_tup_hot_upd
всегда 0, как между UPDATE и SELECT, так и между SELECT и VACUUM. Я также удостоверился, что бегалSELECT pg_sleep(10)
между каждым оператором так, чтобы статистика была актуальной (я вижуseq_scan: 2
, один для ОБНОВЛЕНИЯ и один для ВЫБОР).В особом случае неиндексированной таблицы, да, SELECT может выполнять ту же работу, что и VACUUM (в том, что касается удаления мертвых строк).
источник