Apakah layak menjalankan VACUUM di atas meja yang hanya menerima INSERT?

19

Pada 2015 re: Invent talk, AWS menyebutkan bahwa vakum harus dijalankan tidak hanya setelah pembaruan atau penghapusan tetapi juga setelah sisipan. Inilah bagian yang relevan dari pembicaraan:

http://www.youtube.com/watch?v=tZXp19q8RFo&t=16m2s

Seharusnya ada beberapa pembersihan yang harus dilakukan pada blok bahkan jika mereka hanya menerima sisipan dan pembersihan ini dapat dilakukan baik saat pertama kali blok dipilih (memperlambat membaca) atau selama vakum. Apakah ini benar dan jika demikian, pembersihan apa yang harus dilakukan?

foobar0100
sumber

Jawaban:

15

tl; dr: Proses pertama yang membaca data setelah dilakukan akan menetapkan bit petunjuk. Itu akan mengotori halaman, menciptakan aktivitas menulis. Hal lain VACUUM(tetapi bukan perintah lain) yang dilakukan adalah menandai halaman sebagai semua-terlihat, jika sesuai. VACUUMakhirnya harus menekan meja untuk membekukan tuple.

Pekerjaan yang perlu dilakukan setelah memasukkan tidak benar-benar pembersihan, setidaknya tidak dalam arti pekerjaan lain yang VACUUMbiasanya dilakukan. Sebelum saya masuk ke perinciannya, perhatikan bahwa jawaban ini didasarkan pada kode 9,6 saat ini (yang belum dirilis) dan saya mengabaikan efek replikasi streaming, meskipun itu dapat memengaruhi visibilitas.

Karena MVCC , setiap kali Postgres mengevaluasi apakah sebuah tuple harus dapat dilihat oleh permintaan, ia harus mempertimbangkan apakah transaksi yang membuat tuple (dicatat di bidang tersembunyi xmin) dilakukan, bersama dengan beberapa kriteria lainnya. Cek itu mahal, jadi segera setelah diketahui bahwa transaksi dapat dilihat oleh semua transaksi yang saat ini terbuka, "bit petunjuk" ditetapkan pada tuple header yang mengindikasikan hal itu. Pengaturan bit itu meruntuhkan halaman, yang berarti harus ditulis ke disk. Ini bisa sangat membingungkan jika perintah berikutnya untuk membaca data adalah SELECTyang tiba-tiba menciptakan banyak lalu lintas tulis. Menjalankan aVACUUM setelah memasukkan komitmen akan menghindarinya. Perbedaan penting lainnya adalah ituVACUUMakan SELALU mengisyaratkan tupel pada halaman (selama itu mendapat kunci pembersihan pada halaman), tetapi sebagian besar perintah lain hanya akan mengisyaratkan jika transaksi memasukkan dilakukan sebelum perintah dimulai.

Poin penting tentang penulisan semua bit petunjuk ini adalah yang VACUUMdapat dicekik (dan autovacuum dicekik secara default). Perintah lain tidak dibatasi dan akan menghasilkan data kotor secepat mungkin.

VACUUMadalah satu-satunya metode untuk menandai halaman sebagai semua-terlihat, yang merupakan pertimbangan kinerja yang penting untuk beberapa operasi (terutama, hanya memindai indeks). Jika Anda melakukan penyisipan besar, sangat mungkin ada banyak halaman dengan tuple yang baru dimasukkan. VACUUMdapat berpotensi menandai halaman-halaman itu sebagai semua-terlihat, tetapi hanya jika transaksi yang paling lama berjalan ketika VACUUMdimulai lebih baru daripada transaksi yang memasukkan data .

Karena cara kerja MVCC, tupel yang dimasukkan lebih dari ~ 2 miliar transaksi yang lalu harus ditandai sebagai " beku ". Secara default autovacuum akan melakukan itu setiap 200 juta transaksi. Menjalankan vakum manual dengan vacuum_freeze_min_age diatur ke 0 setelah penyisipan massal dapat membantu mengurangi dampaknya. Lebih agresif, Anda bisa berlari VACUUM FREEZEdi atas meja setelah memasukkan. Itu akan "mengatur ulang jam" pada saat pemindaian pembekuan berikutnya akan terjadi.

Jika Anda ingin mengetahui detail spesifik, lihat HEAPTUPLE_LIVEkasing setelah panggilan ke HeapTupleSatisfiesVacuum()dalam lazy_scan_heap(). Lihat juga HeapTupleSatisfiesVacuum()sendiri, dan bandingkan HeapTupleSatisfiesMVCC().

Ada dua presentasi saya yang mungkin menarik. Video pertama tersedia dari http://www.pgcon.org/2015/schedule/events/829.en.html , sedangkan yang kedua (yang saya pikir sedikit lebih baik) di https://www.youtube. com / watch? v = L8nErzxPJjQ

Jim Nasby
sumber
Ini sangat menarik, dan juga menjelaskan beberapa halaman yang kotor di EXPLAIN (ANALYZE, BUFFERS) outputs. But, if I understand things correctly, some of the hint bits (at least * COMMITTED` dan *INVALID) dapat (dapat) sudah diatur oleh COMMITatau ROLLBACK, kan?
dezso
3
COMMIT dan ROLLBACK tidak benar-benar menyentuh halaman data, jadi tidak, perintah-perintah itu secara khusus tidak pernah bisa mengisyaratkan. Perintah DML masih dapat mengatur status petunjuk xmin dan xmax, baik untuk tuple yang ditandai oleh transaksi lain atau bahkan tupel yang berpotensi yang ditandai oleh transaksi saat ini.
Jim Nasby