Saya mengutak-atik VACUUM
dan memperhatikan beberapa perilaku tak terduga di mana SELECT
baris-baris dari sebuah meja tampaknya mengurangi pekerjaan yang VACUUM
harus dilakukan sesudahnya.
Data Uji
Catatan: autovacuum dinonaktifkan
CREATE TABLE numbers (num bigint);
ALTER TABLE numbers SET (
autovacuum_enabled = 'f',
toast.autovacuum_enabled = 'f'
);
INSERT INTO numbers SELECT generate_series(1, 5000);
Percobaan 1
Sekarang kami menjalankan pembaruan di semua baris,
UPDATE numbers SET num = 0;
Dan ketika kita berlari VACUUM (VERBOSE) numbers;
kita dapatkan,
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.
Percobaan 2
Sekarang kita mengeluarkan yang lain UPDATE
, tapi kali ini kita tambahkan SELECT
sesudahnya,
UPDATE numbers SET num = 1;
SELECT * FROM numbers;
Dan ketika kita berlari VACUUM (VERBOSE) numbers;
kita dapatkan,
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.
Apa sebenarnya yang terjadi di sini? Mengapa versi kedua saya jalankan, setelah SELECT
menghapus tupel mati dari halaman yang dikunjungi, cukup seperti VACUUM
itu?
Saya menjalankan Postgres 11.3 di macOS 10.14.5.
Jawaban:
Dari posting ini di / r / PostgreSQL ke jawaban oleh Laurenz Albe tampaknya pembaruan Heap Only Tuples (HOT) mungkin bertanggung jawab. Dari deskripsi pembaruan HOT di
src/backend/access/heap/README.HOT
Kutipan tidak ada dalam jawaban asli, tetapi sisanya adalah kutipan,
sumber
CREATE INDEX idx_numbers ON numbers USING btree (num)
, output VACUUM berubah menjadiINFO: "numbers": removed 5000 row versions in 45 pages
. Namun perhatikan bahwa dalam skenario indeks-kurang,n_tup_hot_upd
selalu 0, antara UPDATE dan SELECT dan antara SELECT dan VACUUM. Saya juga memastikan untuk menjalankanSELECT pg_sleep(10)
antara setiap pernyataan sehingga statistik terbaru (saya melihatseq_scan: 2
, satu untuk UPDATE dan satu untuk SELECT).Dalam kasus khusus dari tabel yang tidak diindeks, ya, SELECT dapat melakukan pekerjaan yang sama dengan VACUUM (sejauh menghilangkan baris mati yang bersangkutan).
sumber