UPDATE PostgreSQL dapat membuat versi row fisik baru tanpa membuat entry baru yang bersesuaian pada index tuple-addressing biasa. Optimasi heap-only tuple ini, yang umum disebut HOT, berlaku ketika tuple pengganti tetap berada pada heap page yang sama dan update tidak mengubah value yang membuat HOT tidak memenuhi syarat bagi index tabel.

Perbedaan ini penting karena PostgreSQL menerapkan MVCC update dengan mempertahankan versi row, bukan menimpa tuple secara in-place. Tanpa HOT, sebuah update dapat menambah pekerjaan pada heap dan setiap index meskipun value indexed key tetap sama.

HOT mempertahankan referensi index pada sebuah chain

Entry index biasa mengidentifikasi heap tuple melalui tuple identifier. HOT memungkinkan referensi index tersebut tetap berlabuh pada anggota awal version chain sementara versi yang lebih baru menempati line pointer lain pada heap page yang sama.

Secara konseptual, relasinya dapat terlihat seperti ini:

index entry
    |
    v
heap tuple A
    |
    v
heap tuple B
    |
    v
heap tuple C

Tuple berikutnya adalah versi heap-only. Index scan mencapai chain melalui entry index yang sudah ada dan mengikuti on-page version link sesuai kebutuhan MVCC visibility.

Mempertahankan chain pada satu page adalah syarat penting. Tuple identifier memuat block number dan item position, sedangkan HOT bergantung pada page-local redirection dan chain traversal. Jika versi baru tidak muat pada page asal, update tidak dapat menggunakan mekanisme HOT yang sama.

Indexed attribute menentukan batas eligibility

HOT tersedia ketika update tidak memodifikasi attribute yang mengharuskan entry baru pada non-summarizing index. Batas ini mencakup lebih dari sekadar key B-tree satu kolom yang jelas. Expression dan predicate dapat membuat attribute tabel tambahan relevan terhadap index maintenance.

BRIN memiliki semantik berbeda karena merangkum block range, bukan menyimpan entry tuple-addressing untuk setiap indexed row. Rilis PostgreSQL saat ini memperlakukan summarizing index secara terpisah saat menentukan apakah update dapat tetap HOT, meskipun summary-nya masih dapat membutuhkan maintenance.

Batas praktisnya karena itu terkait dengan definisi index tabel secara lengkap, bukan hanya kolom yang tampil sebagai simple index key.

Schema seperti berikut:

CREATE TABLE sessions (
    id bigint PRIMARY KEY,
    account_id bigint NOT NULL,
    state text NOT NULL,
    last_seen_at timestamptz NOT NULL
);

CREATE INDEX sessions_account_id_idx
    ON sessions (account_id);

dapat mengizinkan HOT update pada last_seen_at ketika page space dan kondisi eligibility lainnya terpenuhi. Menambahkan index yang mereferensikan last_seen_at mengubah batas tersebut. Logical update yang sama kemudian dapat membutuhkan index maintenance normal.

Free space menentukan apakah update yang eligible tetap HOT

Attribute eligibility saja tidak cukup. PostgreSQL juga harus menempatkan versi row baru pada heap page yang sama.

Page yang terisi rapat oleh insert mungkin memiliki terlalu sedikit ruang untuk versi lain dari row yang sudah ada. Dalam kondisi tersebut, update yang secara logis cocok dapat menjadi non-HOT karena tuple pengganti harus berpindah ke page lain.

fillfactor tabel memengaruhi probabilitas ini. Fillfactor yang lebih rendah menyisakan ruang yang tidak digunakan selama pengisian page awal, mencadangkan kapasitas yang dapat dipakai update berikutnya. Trade-off-nya adalah physical density: lebih banyak heap page mungkin diperlukan untuk kumpulan row awal yang sama.

Hal ini membuat HOT rate menjadi properti workload, bukan properti schema yang tetap. Tuple width, frekuensi update, page occupancy, definisi index, dan aktivitas pruning semuanya memengaruhi hasil yang diamati.

HOT mengurangi index write amplification

Non-HOT update dapat membuat index tuple baru pada setiap affected index path meskipun banyak key value secara logis tidak berubah. Versi tambahan tersebut menggunakan ruang index, menghasilkan WAL, mengotori index page, dan pada akhirnya menjadi pekerjaan cleanup.

HOT menghilangkan jalur index insertion itu untuk update yang eligible. Heap tetap menerima versi MVCC baru, sehingga optimasi ini tidak mengubah update menjadi in-place overwrite. Efek utamanya adalah memisahkan pembuatan row version yang eligible dari pembuatan per-row index entry.

Perbedaannya menjadi berarti pada tabel dengan beberapa index dan state non-indexed yang sering berubah. Update kecil pada status timestamp atau counter dapat teramplifikasi menjadi write di banyak struktur index.

Page pruning memperpendek HOT chain yang obsolete

HOT chain tidak harus terus bertambah tanpa batas. Setelah versi row lama tidak lagi terlihat oleh relevant snapshot mana pun, PostgreSQL dapat melakukan pruning pada anggota yang obsolete selama page access dan maintenance normal.

Page dapat mempertahankan redirect dari line pointer yang direferensikan index menuju anggota chain yang masih bertahan sambil mereklamasi storage dari dead intermediate version. Cleanup lokal ini menjadi salah satu alasan HOT memiliki dampak di luar penghindaran immediate index write: obsolete heap version dalam HOT chain sering dapat dihapus tanpa menunggu index entry dihapus terlebih dahulu.

Long-running snapshot dapat menunda cleanup tersebut karena versi lama mungkin masih terlihat oleh transaksi aktif. HOT mengurangi index churn, tetapi tidak mengesampingkan aturan MVCC visibility.

Statistik memperlihatkan HOT rate yang benar-benar terjadi

PostgreSQL mencatat counter update dalam statistics view seperti pg_stat_user_tables. Counter n_tup_upd mencatat row yang diperbarui, sedangkan n_tup_hot_upd mencatat update yang dijalankan sebagai HOT update.

Rasio yang diturunkan dari counter tersebut dapat menunjukkan apakah workload benar-benar memperoleh optimasi:

SELECT
    relname,
    n_tup_upd,
    n_tup_hot_upd,
    CASE
        WHEN n_tup_upd = 0 THEN 0
        ELSE n_tup_hot_upd::numeric / n_tup_upd
    END AS hot_ratio
FROM pg_stat_user_tables;

Rasio tersebut bersifat observasional, bukan jaminan. Nilai rendah dapat disebabkan oleh perubahan indexed attribute, page space yang tidak mencukupi, atau workload dengan tuple size dan page occupancy yang menyisakan sedikit ruang untuk versi pada page yang sama.

HOT dengan demikian berada pada persimpangan MVCC, layout heap page, dan index maintenance. Eligibility ditentukan per update, dan manfaatnya konkret: ketika kondisi yang diperlukan terpenuhi, versi row baru dapat tetap dijangkau melalui entry index tuple-addressing yang sudah ada, alih-alih menghasilkan satu set index tuple tambahan.