v5-0023-Set-hastup-in-heap_page_prune.patch
text/x-patch
Filename: v5-0023-Set-hastup-in-heap_page_prune.patch
Type: text/x-patch
Part: 22
Patch
Format: format-patch
Series: patch v5-0023
Subject: Set hastup in heap_page_prune
| File | + | − |
|---|---|---|
| src/backend/access/heap/pruneheap.c | 41 | 23 |
| src/backend/access/heap/vacuumlazy.c | 2 | 22 |
| src/include/access/heapam.h | 2 | 0 |
From d2f59fcb90b206ba9b631bab4dcc1414f17a80af Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 18 Mar 2024 20:12:18 -0400
Subject: [PATCH v5 23/26] Set hastup in heap_page_prune
lazy_scan_prune() loops through the line pointers and tuple visibility
information for each tuple on a page, setting hastup to true if there
are any LP_REDIRECT line pointers or tuples with storage which will not
be removed. We want to remove this extra loop from lazy_scan_prune(),
and we know about non-removable tuples during heap_page_prune() anyway.
Set hastup when recording LP_REDIRECT line pointers in
heap_prune_chain() and when LP_NORMAL line pointers refer to tuples
whose visibility status is not HEAPTUPLE_DEAD.
---
src/backend/access/heap/pruneheap.c | 64 ++++++++++++++++++----------
src/backend/access/heap/vacuumlazy.c | 24 +----------
src/include/access/heapam.h | 2 +
3 files changed, 45 insertions(+), 45 deletions(-)
diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c
index adf6406b880..b44dc149376 100644
--- a/src/backend/access/heap/pruneheap.c
+++ b/src/backend/access/heap/pruneheap.c
@@ -71,7 +71,8 @@ static int heap_prune_chain(Buffer buffer,
static void heap_prune_record_prunable(PruneState *prstate, TransactionId xid);
static void heap_prune_record_redirect(PruneState *prstate,
- OffsetNumber offnum, OffsetNumber rdoffnum);
+ OffsetNumber offnum, OffsetNumber rdoffnum,
+ PruneFreezeResult *presult);
static void heap_prune_record_dead(PruneState *prstate, OffsetNumber offnum,
PruneFreezeResult *presult);
static void heap_prune_record_dead_or_unused(PruneState *prstate, OffsetNumber offnum,
@@ -274,6 +275,8 @@ heap_page_prune_and_freeze(Relation relation, Buffer buffer,
presult->nnewlpdead = 0;
presult->nfrozen = 0;
+ presult->hastup = false;
+
/*
* Caller will update the VM after pruning, collecting LP_DEAD items, and
* freezing tuples. Keep track of whether or not the page is all_visible
@@ -416,30 +419,42 @@ heap_page_prune_and_freeze(Relation relation, Buffer buffer,
break;
}
- /*
- * Consider freezing any normal tuples which will not be removed
- */
- if (presult->htsv[offnum] != HEAPTUPLE_DEAD && pagefrz)
+ if (presult->htsv[offnum] != HEAPTUPLE_DEAD)
{
- bool totally_frozen;
+ /*
+ * Deliberately don't set hastup for LP_DEAD items. We make the
+ * soft assumption that any LP_DEAD items encountered here will
+ * become LP_UNUSED later on, before count_nondeletable_pages is
+ * reached. If we don't make this assumption then rel truncation
+ * will only happen every other VACUUM, at most. Besides, VACUUM
+ * must treat hastup/nonempty_pages as provisional no matter how
+ * LP_DEAD items are handled (handled here, or handled later on).
+ */
+ presult->hastup = true;
- /* Tuple with storage -- consider need to freeze */
- if ((heap_prepare_freeze_tuple(htup, pagefrz,
- &prstate.frozen[presult->nfrozen],
- &totally_frozen)))
+ /* Consider freezing any normal tuples which will not be removed */
+ if (pagefrz)
{
- /* Save prepared freeze plan for later */
- prstate.frozen[presult->nfrozen++].offset = offnum;
- }
+ bool totally_frozen;
- /*
- * If any tuple isn't either totally frozen already or eligible to
- * become totally frozen (according to its freeze plan), then the
- * page definitely cannot be set all-frozen in the visibility map
- * later on
- */
- if (!totally_frozen)
- presult->all_frozen = false;
+ /* Tuple with storage -- consider need to freeze */
+ if ((heap_prepare_freeze_tuple(htup, pagefrz,
+ &prstate.frozen[presult->nfrozen],
+ &totally_frozen)))
+ {
+ /* Save prepared freeze plan for later */
+ prstate.frozen[presult->nfrozen++].offset = offnum;
+ }
+
+ /*
+ * If any tuple isn't either totally frozen already or
+ * eligible to become totally frozen (according to its freeze
+ * plan), then the page definitely cannot be set all-frozen in
+ * the visibility map later on
+ */
+ if (!totally_frozen)
+ presult->all_frozen = false;
+ }
}
}
@@ -993,7 +1008,7 @@ heap_prune_chain(Buffer buffer, OffsetNumber rootoffnum,
if (i >= nchain)
heap_prune_record_dead_or_unused(prstate, rootoffnum, presult);
else
- heap_prune_record_redirect(prstate, rootoffnum, chainitems[i]);
+ heap_prune_record_redirect(prstate, rootoffnum, chainitems[i], presult);
}
else if (nchain < 2 && ItemIdIsRedirected(rootlp))
{
@@ -1027,7 +1042,8 @@ heap_prune_record_prunable(PruneState *prstate, TransactionId xid)
/* Record line pointer to be redirected */
static void
heap_prune_record_redirect(PruneState *prstate,
- OffsetNumber offnum, OffsetNumber rdoffnum)
+ OffsetNumber offnum, OffsetNumber rdoffnum,
+ PruneFreezeResult *presult)
{
Assert(prstate->nredirected < MaxHeapTuplesPerPage);
prstate->redirected[prstate->nredirected * 2] = offnum;
@@ -1037,6 +1053,8 @@ heap_prune_record_redirect(PruneState *prstate,
prstate->marked[offnum] = true;
Assert(!prstate->marked[rdoffnum]);
prstate->marked[rdoffnum] = true;
+
+ presult->hastup = true;
}
/* Record line pointer to be marked dead */
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index fe7751493e2..c87ab76c78e 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -1420,7 +1420,6 @@ lazy_scan_prune(LVRelState *vacrel,
live_tuples,
recently_dead_tuples;
HeapPageFreeze pagefrz;
- bool hastup = false;
OffsetNumber deadoffsets[MaxHeapTuplesPerPage];
Assert(BufferGetBlockNumber(buf) == blkno);
@@ -1477,28 +1476,12 @@ lazy_scan_prune(LVRelState *vacrel,
vacrel->offnum = offnum;
itemid = PageGetItemId(page, offnum);
- if (!ItemIdIsUsed(itemid))
- continue;
-
/* Redirect items mustn't be touched */
- if (ItemIdIsRedirected(itemid))
- {
- /* page makes rel truncation unsafe */
- hastup = true;
+ if (ItemIdIsRedirected(itemid) || !ItemIdIsUsed(itemid))
continue;
- }
if (ItemIdIsDead(itemid))
{
- /*
- * Deliberately don't set hastup for LP_DEAD items. We make the
- * soft assumption that any LP_DEAD items encountered here will
- * become LP_UNUSED later on, before count_nondeletable_pages is
- * reached. If we don't make this assumption then rel truncation
- * will only happen every other VACUUM, at most. Besides, VACUUM
- * must treat hastup/nonempty_pages as provisional no matter how
- * LP_DEAD items are handled (handled here, or handled later on).
- */
deadoffsets[lpdead_items++] = offnum;
continue;
}
@@ -1566,9 +1549,6 @@ lazy_scan_prune(LVRelState *vacrel,
elog(ERROR, "unexpected HeapTupleSatisfiesVacuum result");
break;
}
-
- hastup = true; /* page makes rel truncation unsafe */
-
}
vacrel->offnum = InvalidOffsetNumber;
@@ -1650,7 +1630,7 @@ lazy_scan_prune(LVRelState *vacrel,
vacrel->recently_dead_tuples += recently_dead_tuples;
/* Can't truncate this page */
- if (hastup)
+ if (presult.hastup)
vacrel->nonempty_pages = blkno + 1;
/* Did we find LP_DEAD items? */
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 7a5bc018088..94573a59dd3 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -201,6 +201,8 @@ typedef struct PruneFreezeResult
int ndeleted; /* Number of tuples deleted from the page */
int nnewlpdead; /* Number of newly LP_DEAD items */
bool all_visible; /* Whether or not the page is all visible */
+ bool hastup; /* Does page make rel truncation unsafe */
+
/* Whether or not the page can be set all frozen in the VM */
bool all_frozen;
--
2.39.2