Mengapa VACUUM ANALYZE tidak menghapus semua tupel mati?

8

Kami menjalankan "manual" VACUUM ANALYZE VERBOSEpada beberapa tabel kami yang lebih besar setelah kami melakukan DELETE/INSERTperubahan besar pada mereka. Ini tampaknya bekerja tanpa masalah meskipun kadang-kadang pekerjaan meja VACUUMakan berjalan berjam-jam (lihat posting ini untuk masalah dan alasan yang sama).

Saat melakukan penelitian lebih lanjut, saya menemukan bahwa kami memiliki tabel besar dengan sejumlah besar tupel mati bahkan setelah berjalan VACUUM. Misalnya, berikut adalah beberapa statistik yang dihasilkan dari kueri dalam respons ini .

-[ RECORD 50 ]--+---------------------------
relname         | example_a
last_vacuum     | 2014-09-23 01:43
last_autovacuum | 2014-08-01 01:19
n_tup           |    199,169,568
dead_tup        |    111,048,906
av_threshold    |     39,833,964
expect_av       | *
-[ RECORD 51 ]--+---------------------------
relname         | example_b
last_vacuum     | 2014-09-23 01:48
last_autovacuum | 2014-08-30 12:40
n_tup           |    216,596,624
dead_tup        |    117,224,220
av_threshold    |     43,319,375
expect_av       | *
-[ RECORD 52 ]--+---------------------------
relname         | example_c
last_vacuum     | 2014-09-23 01:55
last_autovacuum | 2014-09-23 18:25
n_tup           |    309,831,136
dead_tup        |    125,047,233
av_threshold    |     61,966,277
expect_av       | *

Bidang terakhir menyatakan bahwa ini (dan sebagian besar tabel) akan memenuhi ambang batas untuk autovacuum. Namun, karena baru saja menjalankan VACUUM ANALYZE VEBOSEmasing-masing tabel tersebut, bukankah jumlah tuple yang mati adalah 0 (atau mendekati 0, bukan 125M dari 300M)?

The dokumentasi menyatakan:

VACUUM mengklaim kembali penyimpanan yang ditempati oleh tupel mati.

Apakah ini berarti kita VACUUMtidak berfungsi?


MEMPERBARUI

Per permintaan di repsonse di sini adalah beberapa log dari VERBOSEpekerjaan:

INFO:  vacuuming "public.example_1"
INFO:  scanned index "idx_example_1_on_gp_id_and_dd_id" to remove 378386 row versions
DETAIL:  CPU 1.83s/3.42u sec elapsed 23.01 sec.
INFO:  scanned index "index_example_1_on_q_id" to remove 378386 row versions
DETAIL:  CPU 2.10s/3.91u sec elapsed 18.92 sec.
INFO:  "example_1": removed 378386 row versions in 7085 pages
DETAIL:  CPU 0.09s/0.05u sec elapsed 0.19 sec.
INFO:  index "idx_example_1_on_gp_id_and_dd_id" now contains 30347438 row versions in 291065 pages
DETAIL:  378386 index row versions were removed.
165587 index pages have been deleted, 164287 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  index "index_example_1_on_q_id" now contains 30347438 row versions in 333287 pages
DETAIL:  378386 index row versions were removed.
152773 index pages have been deleted, 152757 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "example_1": found 1773 removable, 401984 nonremovable row versions in 14438 out of 1493006 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 10567 unused item pointers.
0 pages are entirely empty.
CPU 4.26s/7.51u sec elapsed 46.10 sec.
INFO:  vacuuming "pg_toast.pg_toast_17917"
INFO:  index "pg_toast_17917_index" now contains 0 row versions in 1 pages
DETAIL:  0 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "pg_toast_17917": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  analyzing "public.example_1"
INFO:  "example_1": scanned 30000 of 1493006 pages, containing 611502 live rows and 0 dead rows; 30000 rows in sample, 40563141 estimated total rows

Tabel ini sekarang menunjukkan 0 tupel mati di statistik. Sebagian besar tabel adalah tuple mati jauh lebih rendah pagi ini sehingga VACUUMautovacuum kami atau bekerja.

Kami memiliki beberapa tabel yang tidak menghasilkan apa-apa dan masih menunjukkan tupel yang mati:

-[ RECORD 49 ]--+---------------------------
relname         | example_2
last_vacuum     | 2014-09-23 02:23
last_autovacuum | 2014-09-02 14:30
n_tup           |    117,914,944
dead_tup        |     34,507,388
av_threshold    |     23,583,039
expect_av       | *

Beberapa kali saya lihat di log di mana indeks akan diperiksa berulang-ulang. Ini sepertinya berhubungan dengan VACUUMpekerjaan yang sudah berjalan lama . Ada yang tahu kenapa? Apakah ini hanya bekerja di sekitar penguncian catatan (saya tidak berpikir ada tulisan yang terjadi selama pekerjaan ini dijalankan.)

INFO:  vacuuming "public.example_2"
...
INFO:  scanned index "index_example_2_on_gsg_id_and_dd_id" to remove 2795959 row versions
DETAIL:  CPU 3.88s/16.54u sec elapsed 23.09 sec.
INFO:  scanned index "index_example_2_on_q_id" to remove 2795959 row versions
DETAIL:  CPU 6.74s/21.13u sec elapsed 84.64 sec.
INFO:  "example_2": removed 2795959 row versions in 48214 pages
DETAIL:  CPU 0.71s/0.32u sec elapsed 33.65 sec.
INFO:  scanned index "index_example_2_on_gsg_id_and_dd_id" to remove 2591011 row versions
DETAIL:  CPU 2.84s/16.11u sec elapsed 19.28 sec.
INFO:  scanned index "index_example_2_on_q_id" to remove 2591011 row versions
DETAIL:  CPU 5.46s/22.70u sec elapsed 130.57 sec.
INFO:  "example_2": removed 2591011 row versions in 45539 pages
DETAIL:  CPU 0.67s/0.38u sec elapsed 15.16 sec.
INFO:  index "index_example_2_on_gsg_id_and_dd_id" now contains 123807784 row versions in 1560915 pages
DETAIL:  108836958 index row versions were removed.
1100790 index pages have been deleted, 718471 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.25 sec.
INFO:  index "index_example_2_on_q_id" now contains 123807784 row versions in 1886087 pages
DETAIL:  110336259 index row versions were removed.
1058063 index pages have been deleted, 266983 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.07 sec.
INFO:  "example_2": found 124808 removable, 1355901 nonremovable row versions in 2086343 out of 6966379 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 7858495 unused item pointers.
0 pages are entirely empty.
CPU 595.49s/2130.13u sec elapsed 5656.34 sec.
INFO:  vacuuming "pg_toast.pg_toast_18079"
INFO:  index "pg_toast_18079_index" now contains 0 row versions in 1 pages
DETAIL:  0 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "pg_toast_18079": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  analyzing "public.example_2"
INFO:  "example_2": scanned 30000 of 6966379 pages, containing 528443 live rows and 522 dead rows; 30000 rows in sample, 152953760 estimated total rows
jwadsack
sumber
0 dead row versions cannot be removed yet.menunjukkan Anda tidak memiliki transaksi yang berjalan lama yang akan memblokir penghapusan tupel mati.
Erwin Brandstetter

Jawaban:

10

VACUUM hanya dapat menghapus tupel mati yang sudah lama mati, yaitu mati untuk semua kemungkinan penggunaan. Jika Anda memiliki transaksi jangka panjang, mereka dapat mencegah tupel yang baru mati dihapus.

Ini adalah contoh situasi di mana transaksi jangka panjang mencegah penghapusan:

INFO:  "pgbench_accounts": found 0 removable, 2999042 nonremovable row versions in 49181 out of 163935 pages
DETAIL:  2999000 dead row versions cannot be removed yet.

Ini bukan transaksi yang berumur panjang, tetapi snapshot yang berumur panjang. Tentu saja pilih atau masukkan pernyataan berjalan lama akan melakukan itu. Untuk tingkat isolasi yang lebih tinggi dari komitmen baca, seluruh transaksi akan menyimpan snapshot sampai turun, jadi jika beberapa membuka transaksi baca berulang dan kemudian pergi berlibur tanpa melakukan itu, itu akan menjadi masalah. Transaksi yang disiapkan untuk menutup juga akan terjadi (jika Anda tidak tahu apa transaksi yang disiapkan, maka Anda mungkin tidak menggunakannya).

Contoh yang Anda tunjukkan tidak menunjukkan masalah, tetapi Anda juga mengatakan masalah telah diselesaikan saat itu. Jika ini adalah masalah yang berulang, Anda mungkin harus mulai mencatat output dari pernyataan VACUUM VERBOSE Anda, sehingga Anda dapat menemukan informasi yang mencakup periode selama masalah tersebut terjadi.

Beberapa lintasan melewati indeks adalah karena pengaturan maintenance_work_mem Anda. Itu hanya dapat menghapus satu tuple untuk setiap 6 byte memori pada setiap pass pada indeks, dan perlu membuat beberapa pass jika Anda perlu menghapus lebih dari itu. Jadi meningkatkan maintenance_work_mem akan membantu.

jjanes
sumber
Bisakah Anda memberikan contoh seperti apa "transaksi jangka panjang" itu? Apakah maksud Anda query database yang sudah berjalan lama atau INSERT/ IMPORT? Atau maksud Anda sesuatu yang lebih lama dari koneksi buka / tutup?
jwadsack
4

Ukuran tabel fisik biasanya (kecuali untuk pemangkasan oportunistik dari halaman yang dapat dilepas dari ujung tabel) tidak dikurangi dengan menjalankan VACUUM(atau VACUUM ANALYZE). Anda perlu menjalankan VACUUM FULLuntuk benar-benar mengecilkan tabel.

Ini adalah kutipan dari jawaban terkait, yang memiliki rincian lebih lanjut:

Per dokumentasi (sebenarnya hanya beberapa baris di bawah penawaran Anda):

Polos VACUUM(tanpa FULL) hanya mendapatkan kembali ruang dan membuatnya tersedia untuk digunakan kembali. Bentuk perintah ini dapat beroperasi secara paralel dengan pembacaan dan penulisan tabel normal, karena kunci eksklusif tidak diperoleh. Namun, ruang ekstra tidak dikembalikan ke sistem operasi (dalam kebanyakan kasus);

Lebih banyak di sini:

Anda akan tertarik pada pg_repack , yang dapat melakukan hal yang sama seperti VACUUM FULLtanpa kunci eksklusif.

Erwin Brandstetter
sumber
1
Maaf jika pertanyaan saya tidak jelas, tetapi saya bertanya tentang sisa tuple yang mati. Saya tahu bahwa VACUUMtanpa FULLakan mengurangi ukuran pada disk, dan saya baik-baik saja dengan itu. Saya menyebutkan tabel besar karena posting yang saya tautkan pertama menyatakan bahwa strategi vakum agresif yang disetel akan menjadi "kemenangan ... jika ada tabel besar yang barisnya tidak pernah dihapus atau diperbarui." Meja besar kami diganti setiap hari.
jwadsack