Eu estava brincando VACUUM
e notei algum comportamento inesperado em que SELECT
as linhas de uma tabela parecem reduzir o trabalho que VACUUM
deve ser feito depois.
Dados de teste
Nota: o vácuo automático está desativado
CREATE TABLE numbers (num bigint);
ALTER TABLE numbers SET (
autovacuum_enabled = 'f',
toast.autovacuum_enabled = 'f'
);
INSERT INTO numbers SELECT generate_series(1, 5000);
Julgamento 1
Agora, executamos uma atualização em todas as linhas,
UPDATE numbers SET num = 0;
E quando corremos VACUUM (VERBOSE) numbers;
, chegamos,
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.
Julgamento 2
Agora emitimos outro UPDATE
, mas desta vez adicionamos um SELECT
depois,
UPDATE numbers SET num = 1;
SELECT * FROM numbers;
E quando corremos VACUUM (VERBOSE) numbers;
, chegamos,
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.
O que exatamente está acontecendo aqui? Por que a segunda versão que eu executo, após SELECT
remover tuplas mortas das páginas visitadas, é semelhante a VACUUM
isso?
Estou executando o Postgres 11.3 no macOS 10.14.5.
postgresql
select
vacuum
postgresql-11
rafbm
fonte
fonte
Respostas:
Deste post no / r / PostgreSQL para uma resposta de Laurenz Albe , parece que as atualizações de Heap Only Tuples (HOT) podem ser responsáveis. Na descrição das atualizações HOT em
src/backend/access/heap/README.HOT
A citação não está na resposta original, mas o resto é uma citação,
fonte
CREATE INDEX idx_numbers ON numbers USING btree (num)
, a saída VACUUM muda paraINFO: "numbers": removed 5000 row versions in 45 pages
. Observe, no entanto, que no cenário sem índice,n_tup_hot_upd
é sempre 0, tanto entre UPDATE e SELECT quanto entre SELECT e VACUUM. Também assegurei a execuçãoSELECT pg_sleep(10)
entre cada instrução para que as estatísticas estivessem atualizadas (eu vejoseq_scan: 2
, uma para o UPDATE e outra para o SELECT).No caso especial de uma tabela não indexada, sim, SELECT pode fazer o mesmo trabalho que VACUUM (no que diz respeito à remoção de linhas mortas).
fonte