Skip to content

Commit b0f7425

Browse files
Explain pruning pgstats accounting subtleties.
Add a comment explaining why the pgstats accounting used during opportunistic heap pruning operations (to maintain the current number of dead tuples in the relation) needs to compensate by subtracting away the number of new LP_DEAD items. This is needed so it can avoid completely forgetting about tuples that become LP_DEAD items during pruning -- they should still count. It seems more natural to discuss this issue at the only relevant call site (opportunistic pruning), since the same issue does not apply to the only other caller (the VACUUM call site). Move everything there too. Author: Peter Geoghegan <pg@bowt.ie> Discussion: https://postgr.es/m/CAH2-Wzm7f+A6ej650gi_ifTgbhsadVW5cujAL3punpupHff5Yg@mail.gmail.com
1 parent 05d8785 commit b0f7425

File tree

3 files changed

+31
-18
lines changed

3 files changed

+31
-18
lines changed

src/backend/access/heap/pruneheap.c

+28-16
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,29 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
182182
*/
183183
if (PageIsFull(page) || PageGetHeapFreeSpace(page) < minfree)
184184
{
185-
/* OK to prune */
186-
(void) heap_page_prune(relation, buffer, vistest,
187-
limited_xmin, limited_ts,
188-
true, NULL);
185+
int ndeleted,
186+
nnewlpdead;
187+
188+
ndeleted = heap_page_prune(relation, buffer, vistest, limited_xmin,
189+
limited_ts, &nnewlpdead, NULL);
190+
191+
/*
192+
* Report the number of tuples reclaimed to pgstats. This is
193+
* ndeleted minus the number of newly-LP_DEAD-set items.
194+
*
195+
* We derive the number of dead tuples like this to avoid totally
196+
* forgetting about items that were set to LP_DEAD, since they
197+
* still need to be cleaned up by VACUUM. We only want to count
198+
* heap-only tuples that just became LP_UNUSED in our report,
199+
* which don't.
200+
*
201+
* VACUUM doesn't have to compensate in the same way when it
202+
* tracks ndeleted, since it will set the same LP_DEAD items to
203+
* LP_UNUSED separately.
204+
*/
205+
if (ndeleted > nnewlpdead)
206+
pgstat_update_heap_dead_tuples(relation,
207+
ndeleted - nnewlpdead);
189208
}
190209

191210
/* And release buffer lock */
@@ -212,10 +231,8 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
212231
* either have been set by TransactionIdLimitedForOldSnapshots, or
213232
* InvalidTransactionId/0 respectively.
214233
*
215-
* If report_stats is true then we send the number of reclaimed heap-only
216-
* tuples to pgstats. (This must be false during vacuum, since vacuum will
217-
* send its own new total to pgstats, and we don't want this delta applied
218-
* on top of that.)
234+
* Sets *nnewlpdead for caller, indicating the number of items that were
235+
* newly set LP_DEAD during prune operation.
219236
*
220237
* off_loc is the offset location required by the caller to use in error
221238
* callback.
@@ -227,7 +244,7 @@ heap_page_prune(Relation relation, Buffer buffer,
227244
GlobalVisState *vistest,
228245
TransactionId old_snap_xmin,
229246
TimestampTz old_snap_ts,
230-
bool report_stats,
247+
int *nnewlpdead,
231248
OffsetNumber *off_loc)
232249
{
233250
int ndeleted = 0;
@@ -381,13 +398,8 @@ heap_page_prune(Relation relation, Buffer buffer,
381398

382399
END_CRIT_SECTION();
383400

384-
/*
385-
* If requested, report the number of tuples reclaimed to pgstats. This is
386-
* ndeleted minus ndead, because we don't want to count a now-DEAD root
387-
* item as a deletion for this purpose.
388-
*/
389-
if (report_stats && ndeleted > prstate.ndead)
390-
pgstat_update_heap_dead_tuples(relation, ndeleted - prstate.ndead);
401+
/* Record number of newly-set-LP_DEAD items for caller */
402+
*nnewlpdead = prstate.ndead;
391403

392404
return ndeleted;
393405
}

src/backend/access/heap/vacuumlazy.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1712,6 +1712,7 @@ lazy_scan_prune(LVRelState *vacrel,
17121712
new_dead_tuples,
17131713
num_tuples,
17141714
live_tuples;
1715+
int nnewlpdead;
17151716
int nfrozen;
17161717
OffsetNumber deadoffsets[MaxHeapTuplesPerPage];
17171718
xl_heap_freeze_tuple frozen[MaxHeapTuplesPerPage];
@@ -1737,7 +1738,7 @@ lazy_scan_prune(LVRelState *vacrel,
17371738
* that were deleted from indexes.
17381739
*/
17391740
tuples_deleted = heap_page_prune(rel, buf, vistest,
1740-
InvalidTransactionId, 0, false,
1741+
InvalidTransactionId, 0, &nnewlpdead,
17411742
&vacrel->offnum);
17421743

17431744
/*

src/include/access/heapam.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ extern int heap_page_prune(Relation relation, Buffer buffer,
186186
struct GlobalVisState *vistest,
187187
TransactionId old_snap_xmin,
188188
TimestampTz old_snap_ts_ts,
189-
bool report_stats,
189+
int *nnewlpdead,
190190
OffsetNumber *off_loc);
191191
extern void heap_page_prune_execute(Buffer buffer,
192192
OffsetNumber *redirected, int nredirected,

0 commit comments

Comments
 (0)