PostgreSQL menyimpan metadata visibility tuple di row heap, tetapi memeriksa setiap tuple heap tidak diperlukan ketika seluruh page sudah diketahui memenuhi kondisi yang lebih kuat. Visibility map menyimpan status tingkat page tersebut dalam relation fork yang ringkas.

Setiap heap page memiliki dua bit yang bersesuaian. Bit all-visible mencatat bahwa setiap tuple pada page terlihat oleh setiap transaksi saat ini dan mendatang. Bit all-frozen mencatat bahwa setiap tuple pada page telah dibekukan. Fakta tersebut memungkinkan PostgreSQL menghindari pekerjaan dalam index-only scan dan operasi vacuum tanpa memindahkan data visibility MVCC ke dalam index.

Map ini sengaja bersifat konservatif. Bit yang diset menegaskan kondisi yang telah dibuktikan PostgreSQL. Bit yang clear tidak menegaskan kebalikannya; kondisi itu bisa sekadar berarti page tersebut belum terbukti memenuhi kondisi yang dimaksud.

Dua bit menggambarkan properti page yang berbeda

Status all-visible dan all-frozen saling berkaitan, tetapi keduanya digunakan untuk keputusan yang berbeda.

Page all-visible tidak berisi tuple yang memerlukan pemeriksaan visibility khusus transaksi. Status inilah yang dapat digunakan index-only scan untuk menghindari pengambilan tuple heap yang cocok. Index PostgreSQL umumnya mengidentifikasi tuple heap, tetapi tidak membawa cukup informasi MVCC untuk menentukan visibility tuple sendiri.

Page all-frozen melangkah lebih jauh. Tuple di dalamnya tidak lagi memerlukan proses freezing pada masa mendatang untuk transaction identifier-nya. Vacuum dapat menggunakan status tersebut saat menentukan page mana yang dapat dilewati, termasuk selama maintenance yang berkaitan dengan usia transaction ID.

Perbedaannya penting karena sebuah page dapat all-visible tanpa belum menjadi all-frozen. Visibility terhadap transaksi saat ini dan mendatang tidak dengan sendirinya berarti setiap transaction identifier yang relevan pada page tersebut sudah dibekukan.

Index-only scan memeriksa status page

Sebuah index dapat memuat setiap column yang diperlukan query tetapi tetap memerlukan akses heap. PostgreSQL juga harus memastikan bahwa setiap kandidat tuple terlihat oleh transaksi saat ini.

Untuk index-only scan, executor dapat memeriksa visibility map menggunakan heap block yang dirujuk oleh index entry. Jika heap page tersebut ditandai all-visible, executor dapat mengembalikan nilai dari index tanpa mengunjungi heap untuk pemeriksaan visibility.

index entry
    |
    +-- heap block 418
            |
            +-- VM all-visible = 1 -> heap fetch can be skipped
            |
            +-- VM all-visible = 0 -> inspect heap tuple

Hal ini membuat index coverage dan page visibility menjadi dua kondisi terpisah. Menambahkan included column dapat membuat query secara struktural memenuhi syarat untuk index-only scan, sementara write yang sering tetap dapat menyebabkan heap fetch karena page yang dimodifikasi kehilangan status all-visible.

Visibility map jauh lebih kecil daripada heap karena hanya menyimpan dua bit per heap page. Karena itu, memeriksanya dapat menghindari akses heap dengan overhead metadata yang kecil.

Vacuum menetapkan fakta page yang dapat digunakan kembali

VACUUM bertanggung jawab menyetel bit visibility map setelah memeriksa heap page dan membuktikan kondisi yang diperlukan. Operasi yang memodifikasi data menghapus status yang relevan ketika sebuah page tidak lagi dapat diasumsikan memenuhi kondisi tersebut.

Asimetri ini melindungi correctness. Menghapus bit terlalu awal hanya menyebabkan pekerjaan tambahan nanti. Menyetel bit tanpa membuktikan kondisinya dapat membuat PostgreSQL melewati pekerjaan yang sebenarnya diperlukan untuk visibility atau maintenance.

Page yang telah stabil setelah periode write dapat menjadi all-visible setelah vacuum memprosesnya. Jika tuple-nya juga telah dibekukan, bit all-frozen juga dapat diset. Modifikasi berikutnya membatalkan shortcut tingkat page tersebut sampai maintenance dapat membuktikan statusnya kembali.

Perilaku ini menghubungkan pola write dengan perilaku read. Tabel yang sebagian besar statis dapat mengakumulasi bagian all-visible yang besar, sehingga index-only scan memiliki banyak peluang untuk menghindari akses heap. Tabel yang page-nya terus dimodifikasi mungkin menawarkan lebih sedikit peluang seperti itu meskipun index yang sesuai tersedia.

Vacuum juga menggunakan map untuk membatasi scanning

Map ini bukan hanya optimasi executor. Vacuum memeriksanya untuk menentukan heap page mana yang perlu diperiksa.

Page yang diketahui tidak memiliki tuple yang membutuhkan cleanup dapat dilewati selama pemrosesan vacuum biasa. Page all-frozen memberikan kondisi yang lebih kuat: maintenance yang berkaitan dengan transaction identifier lama dapat melewatinya karena tidak ada lagi pekerjaan freezing pada page tersebut.

Karena itu, tidak setiap vacuum pass harus membaca setiap heap page. Visibility map mempertahankan fakta yang dibuktikan oleh pekerjaan sebelumnya dan memungkinkan maintenance berikutnya berfokus pada page yang statusnya masih perlu diperiksa.

Perilaku aggressive vacuum berbeda dari pass biasa karena penuaan transaction ID dapat mengharuskan pemeriksaan page yang all-visible tetapi belum all-frozen. Kedua bit yang terpisah memungkinkan PostgreSQL membedakan kasus tersebut alih-alih memperlakukan visibility dan freezing sebagai satu properti.

Bit yang clear bukan bukti bahwa page bermasalah

Desain konservatif ini berguna saat menginterpretasikan data visibility secara operasional. Bit all-visible yang tidak diset tidak membuktikan bahwa page tersebut berisi tuple yang tidak terlihat oleh suatu transaksi. Itu hanya berarti PostgreSQL saat ini tidak dapat mengandalkan pernyataan all-visible yang lebih kuat.

Prinsip yang sama berlaku untuk status all-frozen. Tidak adanya bit berarti page tidak dapat dilewati hanya berdasarkan pernyataan tersebut.

Extension pg_visibility mengekspos status visibility map untuk inspeksi. Extension ini dapat melaporkan informasi all-visible dan all-frozen per block serta merangkum jumlahnya untuk sebuah relation. Hal ini dapat membantu memisahkan desain index dari heap visibility ketika execution plan index-only masih melaporkan heap fetch.

Estimasi catalog memberikan pandangan yang lebih luas. pg_class.relallvisible mencatat estimasi jumlah page yang ditandai all-visible, sedangkan relallfrozen mencatat estimasi jumlah page yang ditandai all-frozen. Inspeksi tingkat block yang presisi dan estimasi catalog melayani kebutuhan diagnosis yang berbeda.

Status page menghubungkan MVCC, index, dan maintenance

Visibility map berukuran kecil, tetapi berada pada batas yang digunakan bersama oleh beberapa subsystem PostgreSQL. MVCC menentukan apakah versi tuple terlihat, vacuum menetapkan fakta tingkat page, dan index-only scan menggunakan salah satu fakta tersebut untuk menghindari read heap.

Pemisahan ini membuat index tidak perlu membawa seluruh status visibility tuple sambil tetap memungkinkan heap page yang stabil menjadi lebih murah untuk di-query. Hal ini juga memungkinkan vacuum mempertahankan pengetahuan dari pass sebelumnya alih-alih menemukan kembali setiap kondisi page pada setiap run.

Ketika index-only scan melakukan lebih banyak heap fetch daripada yang diperkirakan, isi index hanya merupakan sebagian dari gambaran. Status visibility dari heap page yang dirujuk merupakan kondisi lain, dan status tersebut berubah mengikuti write serta aktivitas vacuum berikutnya.