Skip to content

Commit 26d138f

Browse files
committed
Refactor how heap_prune_chain() updates prunable_xid
In preparation of freezing and counting tuples which are not candidates for pruning, split heap_prune_record_unchanged() into multiple functions, depending the kind of line pointer. That's not too interesting right now, but makes the next commit smaller. Recording the lowest soon-to-be prunable xid is one of the actions we take for unchanged LP_NORMAL item pointers but not for others, so move that to the new heap_prune_record_unchanged_lp_normal() function. The next commit will add more actions to these functions. Author: Melanie Plageman <melanieplageman@gmail.com> Discussion: https://www.postgresql.org/message-id/20240330055710.kqg6ii2cdojsxgje@liskov
1 parent be2f073 commit 26d138f

File tree

1 file changed

+92
-33
lines changed

1 file changed

+92
-33
lines changed

src/backend/access/heap/pruneheap.c

Lines changed: 92 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,11 @@ static void heap_prune_record_redirect(PruneState *prstate,
7878
static void heap_prune_record_dead(PruneState *prstate, OffsetNumber offnum, bool was_normal);
7979
static void heap_prune_record_dead_or_unused(PruneState *prstate, OffsetNumber offnum, bool was_normal);
8080
static void heap_prune_record_unused(PruneState *prstate, OffsetNumber offnum, bool was_normal);
81-
static void heap_prune_record_unchanged(PruneState *prstate, OffsetNumber offnum);
81+
82+
static void heap_prune_record_unchanged_lp_unused(Page page, PruneState *prstate, OffsetNumber offnum);
83+
static void heap_prune_record_unchanged_lp_normal(Page page, int8 *htsv, PruneState *prstate, OffsetNumber offnum);
84+
static void heap_prune_record_unchanged_lp_dead(Page page, PruneState *prstate, OffsetNumber offnum);
85+
static void heap_prune_record_unchanged_lp_redirect(PruneState *prstate, OffsetNumber offnum);
8286

8387
static void page_verify_redirects(Page page);
8488

@@ -311,7 +315,7 @@ heap_page_prune(Relation relation, Buffer buffer,
311315
/* Nothing to do if slot doesn't contain a tuple */
312316
if (!ItemIdIsUsed(itemid))
313317
{
314-
heap_prune_record_unchanged(&prstate, offnum);
318+
heap_prune_record_unchanged_lp_unused(page, &prstate, offnum);
315319
continue;
316320
}
317321

@@ -324,7 +328,7 @@ heap_page_prune(Relation relation, Buffer buffer,
324328
if (unlikely(prstate.mark_unused_now))
325329
heap_prune_record_unused(&prstate, offnum, false);
326330
else
327-
heap_prune_record_unchanged(&prstate, offnum);
331+
heap_prune_record_unchanged_lp_dead(page, &prstate, offnum);
328332
continue;
329333
}
330334

@@ -434,7 +438,7 @@ heap_page_prune(Relation relation, Buffer buffer,
434438
}
435439
}
436440
else
437-
heap_prune_record_unchanged(&prstate, offnum);
441+
heap_prune_record_unchanged_lp_normal(page, presult->htsv, &prstate, offnum);
438442
}
439443

440444
/* We should now have processed every tuple exactly once */
@@ -652,9 +656,6 @@ heap_prune_chain(Page page, BlockNumber blockno, OffsetNumber maxoff,
652656
*/
653657
chainitems[nchain++] = offnum;
654658

655-
/*
656-
* Check tuple's visibility status.
657-
*/
658659
switch (htsv_get_valid_status(htsv[offnum]))
659660
{
660661
case HEAPTUPLE_DEAD:
@@ -670,9 +671,6 @@ heap_prune_chain(Page page, BlockNumber blockno, OffsetNumber maxoff,
670671
case HEAPTUPLE_RECENTLY_DEAD:
671672

672673
/*
673-
* This tuple may soon become DEAD. Update the hint field so
674-
* that the page is reconsidered for pruning in future.
675-
*
676674
* We don't need to advance the conflict horizon for
677675
* RECENTLY_DEAD tuples, even if we are removing them. This
678676
* is because we only remove RECENTLY_DEAD tuples if they
@@ -681,8 +679,6 @@ heap_prune_chain(Page page, BlockNumber blockno, OffsetNumber maxoff,
681679
* tuple by virtue of being later in the chain. We will have
682680
* advanced the conflict horizon for the DEAD tuple.
683681
*/
684-
heap_prune_record_prunable(prstate,
685-
HeapTupleHeaderGetUpdateXid(htup));
686682

687683
/*
688684
* Advance past RECENTLY_DEAD tuples just in case there's a
@@ -693,24 +689,8 @@ heap_prune_chain(Page page, BlockNumber blockno, OffsetNumber maxoff,
693689
break;
694690

695691
case HEAPTUPLE_DELETE_IN_PROGRESS:
696-
697-
/*
698-
* This tuple may soon become DEAD. Update the hint field so
699-
* that the page is reconsidered for pruning in future.
700-
*/
701-
heap_prune_record_prunable(prstate,
702-
HeapTupleHeaderGetUpdateXid(htup));
703-
goto process_chain;
704-
705692
case HEAPTUPLE_LIVE:
706693
case HEAPTUPLE_INSERT_IN_PROGRESS:
707-
708-
/*
709-
* If we wanted to optimize for aborts, we might consider
710-
* marking the page prunable when we see INSERT_IN_PROGRESS.
711-
* But we don't. See related decisions about when to mark the
712-
* page prunable in heapam.c.
713-
*/
714694
goto process_chain;
715695

716696
default:
@@ -757,8 +737,15 @@ heap_prune_chain(Page page, BlockNumber blockno, OffsetNumber maxoff,
757737
* No DEAD tuple was found, so the chain is entirely composed of
758738
* normal, unchanged tuples. Leave it alone.
759739
*/
760-
for (int i = 0; i < nchain; i++)
761-
heap_prune_record_unchanged(prstate, chainitems[i]);
740+
int i = 0;
741+
742+
if (ItemIdIsRedirected(rootlp))
743+
{
744+
heap_prune_record_unchanged_lp_redirect(prstate, rootoffnum);
745+
i++;
746+
}
747+
for (; i < nchain; i++)
748+
heap_prune_record_unchanged_lp_normal(page, htsv, prstate, chainitems[i]);
762749
}
763750
else if (ndeadchain == nchain)
764751
{
@@ -784,7 +771,7 @@ heap_prune_chain(Page page, BlockNumber blockno, OffsetNumber maxoff,
784771

785772
/* the rest of tuples in the chain are normal, unchanged tuples */
786773
for (int i = ndeadchain; i < nchain; i++)
787-
heap_prune_record_unchanged(prstate, chainitems[i]);
774+
heap_prune_record_unchanged_lp_normal(page, htsv, prstate, chainitems[i]);
788775
}
789776
}
790777

@@ -894,9 +881,81 @@ heap_prune_record_unused(PruneState *prstate, OffsetNumber offnum, bool was_norm
894881
prstate->ndeleted++;
895882
}
896883

897-
/* Record a line pointer that is left unchanged */
884+
/*
885+
* Record an unused line pointer that is left unchanged.
886+
*/
887+
static void
888+
heap_prune_record_unchanged_lp_unused(Page page, PruneState *prstate, OffsetNumber offnum)
889+
{
890+
Assert(!prstate->processed[offnum]);
891+
prstate->processed[offnum] = true;
892+
}
893+
894+
/*
895+
* Record LP_NORMAL line pointer that is left unchanged.
896+
*/
897+
static void
898+
heap_prune_record_unchanged_lp_normal(Page page, int8 *htsv, PruneState *prstate, OffsetNumber offnum)
899+
{
900+
HeapTupleHeader htup;
901+
902+
Assert(!prstate->processed[offnum]);
903+
prstate->processed[offnum] = true;
904+
905+
switch (htsv[offnum])
906+
{
907+
case HEAPTUPLE_LIVE:
908+
case HEAPTUPLE_INSERT_IN_PROGRESS:
909+
910+
/*
911+
* If we wanted to optimize for aborts, we might consider marking
912+
* the page prunable when we see INSERT_IN_PROGRESS. But we
913+
* don't. See related decisions about when to mark the page
914+
* prunable in heapam.c.
915+
*/
916+
break;
917+
918+
case HEAPTUPLE_RECENTLY_DEAD:
919+
case HEAPTUPLE_DELETE_IN_PROGRESS:
920+
921+
htup = (HeapTupleHeader) PageGetItem(page, PageGetItemId(page, offnum));
922+
923+
/*
924+
* This tuple may soon become DEAD. Update the hint field so that
925+
* the page is reconsidered for pruning in future.
926+
*/
927+
heap_prune_record_prunable(prstate,
928+
HeapTupleHeaderGetUpdateXid(htup));
929+
break;
930+
931+
932+
default:
933+
934+
/*
935+
* DEAD tuples should've been passed to heap_prune_record_dead()
936+
* or heap_prune_record_unused() instead.
937+
*/
938+
elog(ERROR, "unexpected HeapTupleSatisfiesVacuum result %d", htsv[offnum]);
939+
break;
940+
}
941+
}
942+
943+
944+
/*
945+
* Record line pointer that was already LP_DEAD and is left unchanged.
946+
*/
947+
static void
948+
heap_prune_record_unchanged_lp_dead(Page page, PruneState *prstate, OffsetNumber offnum)
949+
{
950+
Assert(!prstate->processed[offnum]);
951+
prstate->processed[offnum] = true;
952+
}
953+
954+
/*
955+
* Record LP_REDIRECT that is left unchanged.
956+
*/
898957
static void
899-
heap_prune_record_unchanged(PruneState *prstate, OffsetNumber offnum)
958+
heap_prune_record_unchanged_lp_redirect(PruneState *prstate, OffsetNumber offnum)
900959
{
901960
Assert(!prstate->processed[offnum]);
902961
prstate->processed[offnum] = true;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy