]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Save prune cycles by consistently clearing prune hints on all-visible pages
authorMelanie Plageman <melanieplageman@gmail.com>
Mon, 2 Mar 2026 16:05:59 +0000 (11:05 -0500)
committerMelanie Plageman <melanieplageman@gmail.com>
Mon, 2 Mar 2026 16:05:59 +0000 (11:05 -0500)
All-visible pages can't contain prunable tuples. We already clear the
prune hint (pd_prune_xid) during pruning of all-visible pages, but we
were not doing so in vacuum phase three, nor initializing it for
all-frozen pages created by COPY FREEZE, and we were not clearing it on
standbys.

Because page hints are not WAL-logged, pages on a standby carry stale
pd_prune_xid values. After promotion, that stale hint triggers
unnecessary on-access pruning.

Fix this by clearing the prune hint everywhere we currently mark a heap
page all-visible. Clearing it when setting PD_ALL_VISIBLE ensures no
extra overhead.

Author: Melanie Plageman <melanieplageman@gmail.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/flat/CAAKRu_b-BMOyu0X-0jc_8bWNSbQ5K6JTEueayEhcQuw-OkCSKg%40mail.gmail.com

src/backend/access/heap/heapam.c
src/backend/access/heap/heapam_xlog.c
src/backend/access/heap/vacuumlazy.c

index d534258e5478b3e4787dd8901b1fb0a4a1d8090b..a231563f0dfecd7f1d6f3f8086c9555363cb261c 100644 (file)
@@ -2578,6 +2578,7 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
                else if (all_frozen_set)
                {
                        PageSetAllVisible(page);
+                       PageClearPrunable(page);
                        visibilitymap_set_vmbits(BufferGetBlockNumber(buffer),
                                                                         vmbuffer,
                                                                         VISIBILITYMAP_ALL_VISIBLE |
index f765345e9e44d04aced07ef39835e151f74c1dbd..6d39a5fff7cf603dcc2bd3924a5c27a2de5be868 100644 (file)
@@ -164,7 +164,10 @@ heap_xlog_prune_freeze(XLogReaderState *record)
                 * modification would fail to clear the visibility map bit.
                 */
                if (vmflags & VISIBILITYMAP_VALID_BITS)
+               {
                        PageSetAllVisible(page);
+                       PageClearPrunable(page);
+               }
 
                MarkBufferDirty(buffer);
 
@@ -305,6 +308,7 @@ heap_xlog_visible(XLogReaderState *record)
                page = BufferGetPage(buffer);
 
                PageSetAllVisible(page);
+               PageClearPrunable(page);
 
                if (XLogHintBitIsNeeded())
                        PageSetLSN(page, lsn);
@@ -734,7 +738,10 @@ heap_xlog_multi_insert(XLogReaderState *record)
 
                /* XLH_INSERT_ALL_FROZEN_SET implies that all tuples are visible */
                if (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET)
+               {
                        PageSetAllVisible(page);
+                       PageClearPrunable(page);
+               }
 
                MarkBufferDirty(buffer);
        }
index 5d271d809672bc3cc0ff4fea6a38aa71304c2315..5b6f2441f6bef3c9f40e79ff10129a2307b56c5c 100644 (file)
@@ -1933,6 +1933,7 @@ lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, BlockNumber blkno,
                                log_newpage_buffer(buf, true);
 
                        PageSetAllVisible(page);
+                       PageClearPrunable(page);
                        visibilitymap_set(vacrel->rel, blkno, buf,
                                                          InvalidXLogRecPtr,
                                                          vmbuffer, InvalidTransactionId,
@@ -2209,6 +2210,7 @@ lazy_scan_prune(LVRelState *vacrel,
         * the VM bits clear, so there is no point in optimizing it.
         */
        PageSetAllVisible(page);
+       PageClearPrunable(page);
        MarkBufferDirty(buf);
 
        /*
@@ -2944,6 +2946,7 @@ lazy_vacuum_heap_page(LVRelState *vacrel, BlockNumber blkno, Buffer buffer,
                 * set PD_ALL_VISIBLE.
                 */
                PageSetAllVisible(page);
+               PageClearPrunable(page);
                visibilitymap_set_vmbits(blkno,
                                                                 vmbuffer, vmflags,
                                                                 vacrel->rel->rd_locator);