@@ -78,7 +78,11 @@ static void heap_prune_record_redirect(PruneState *prstate,
78
78
static void heap_prune_record_dead (PruneState * prstate , OffsetNumber offnum , bool was_normal );
79
79
static void heap_prune_record_dead_or_unused (PruneState * prstate , OffsetNumber offnum , bool was_normal );
80
80
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 );
82
86
83
87
static void page_verify_redirects (Page page );
84
88
@@ -311,7 +315,7 @@ heap_page_prune(Relation relation, Buffer buffer,
311
315
/* Nothing to do if slot doesn't contain a tuple */
312
316
if (!ItemIdIsUsed (itemid ))
313
317
{
314
- heap_prune_record_unchanged ( & prstate , offnum );
318
+ heap_prune_record_unchanged_lp_unused ( page , & prstate , offnum );
315
319
continue ;
316
320
}
317
321
@@ -324,7 +328,7 @@ heap_page_prune(Relation relation, Buffer buffer,
324
328
if (unlikely (prstate .mark_unused_now ))
325
329
heap_prune_record_unused (& prstate , offnum , false);
326
330
else
327
- heap_prune_record_unchanged ( & prstate , offnum );
331
+ heap_prune_record_unchanged_lp_dead ( page , & prstate , offnum );
328
332
continue ;
329
333
}
330
334
@@ -434,7 +438,7 @@ heap_page_prune(Relation relation, Buffer buffer,
434
438
}
435
439
}
436
440
else
437
- heap_prune_record_unchanged ( & prstate , offnum );
441
+ heap_prune_record_unchanged_lp_normal ( page , presult -> htsv , & prstate , offnum );
438
442
}
439
443
440
444
/* We should now have processed every tuple exactly once */
@@ -652,9 +656,6 @@ heap_prune_chain(Page page, BlockNumber blockno, OffsetNumber maxoff,
652
656
*/
653
657
chainitems [nchain ++ ] = offnum ;
654
658
655
- /*
656
- * Check tuple's visibility status.
657
- */
658
659
switch (htsv_get_valid_status (htsv [offnum ]))
659
660
{
660
661
case HEAPTUPLE_DEAD :
@@ -670,9 +671,6 @@ heap_prune_chain(Page page, BlockNumber blockno, OffsetNumber maxoff,
670
671
case HEAPTUPLE_RECENTLY_DEAD :
671
672
672
673
/*
673
- * This tuple may soon become DEAD. Update the hint field so
674
- * that the page is reconsidered for pruning in future.
675
- *
676
674
* We don't need to advance the conflict horizon for
677
675
* RECENTLY_DEAD tuples, even if we are removing them. This
678
676
* is because we only remove RECENTLY_DEAD tuples if they
@@ -681,8 +679,6 @@ heap_prune_chain(Page page, BlockNumber blockno, OffsetNumber maxoff,
681
679
* tuple by virtue of being later in the chain. We will have
682
680
* advanced the conflict horizon for the DEAD tuple.
683
681
*/
684
- heap_prune_record_prunable (prstate ,
685
- HeapTupleHeaderGetUpdateXid (htup ));
686
682
687
683
/*
688
684
* Advance past RECENTLY_DEAD tuples just in case there's a
@@ -693,24 +689,8 @@ heap_prune_chain(Page page, BlockNumber blockno, OffsetNumber maxoff,
693
689
break ;
694
690
695
691
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
-
705
692
case HEAPTUPLE_LIVE :
706
693
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
- */
714
694
goto process_chain ;
715
695
716
696
default :
@@ -757,8 +737,15 @@ heap_prune_chain(Page page, BlockNumber blockno, OffsetNumber maxoff,
757
737
* No DEAD tuple was found, so the chain is entirely composed of
758
738
* normal, unchanged tuples. Leave it alone.
759
739
*/
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 ]);
762
749
}
763
750
else if (ndeadchain == nchain )
764
751
{
@@ -784,7 +771,7 @@ heap_prune_chain(Page page, BlockNumber blockno, OffsetNumber maxoff,
784
771
785
772
/* the rest of tuples in the chain are normal, unchanged tuples */
786
773
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 ]);
788
775
}
789
776
}
790
777
@@ -894,9 +881,81 @@ heap_prune_record_unused(PruneState *prstate, OffsetNumber offnum, bool was_norm
894
881
prstate -> ndeleted ++ ;
895
882
}
896
883
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
+ */
898
957
static void
899
- heap_prune_record_unchanged (PruneState * prstate , OffsetNumber offnum )
958
+ heap_prune_record_unchanged_lp_redirect (PruneState * prstate , OffsetNumber offnum )
900
959
{
901
960
Assert (!prstate -> processed [offnum ]);
902
961
prstate -> processed [offnum ] = true;
0 commit comments