diff options
author | Peter Geoghegan <pg@bowt.ie> | 2021-04-07 08:47:15 -0700 |
---|---|---|
committer | Peter Geoghegan <pg@bowt.ie> | 2021-04-07 08:47:15 -0700 |
commit | 3c3b8a4b26891892bccf3d220580a7f413c0b9ca (patch) | |
tree | 1f734ebb5c56cf901065e7b55bcc2033325b1d73 /src/backend/access/heap/heapam.c | |
parent | 3db826bd55cd1df0dd8c3d811f8e5b936d7ba1e4 (diff) |
Truncate line pointer array during VACUUM.
Teach VACUUM to truncate the line pointer array of each heap page when a
contiguous group of LP_UNUSED line pointers appear at the end of the
array -- these unused and unreferenced items are excluded. This process
occurs during VACUUM's second pass over the heap, right after LP_DEAD
line pointers on the page (those encountered/pruned during the first
pass) are marked LP_UNUSED.
Truncation avoids line pointer bloat with certain workloads,
particularly those involving continual range DELETEs and bulk INSERTs
against the same table.
Also harden heapam code to check for an out-of-range page offset number
in places where we weren't already doing so.
Author: Matthias van de Meent <boekewurm+postgres@gmail.com>
Author: Peter Geoghegan <pg@bowt.ie>
Reviewed-By: Masahiko Sawada <sawada.mshk@gmail.com>
Reviewed-By: Peter Geoghegan <pg@bowt.ie>
Discussion: https://postgr.es/m/CAEze2WjgaQc55Y5f5CQd3L=eS5CZcff2Obxp=O6pto8-f0hC4w@mail.gmail.com
Discussion: https://postgr.es/m/CAH2-Wzn6a64PJM1Ggzm=uvx2otsopJMhFQj_g1rAj4GWr3ZSzw@mail.gmail.com
Diffstat (limited to 'src/backend/access/heap/heapam.c')
-rw-r--r-- | src/backend/access/heap/heapam.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 9cbc161d7a9..03d4abc938b 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -635,8 +635,15 @@ heapgettup(HeapScanDesc scan, } else { + /* + * The previous returned tuple may have been vacuumed since the + * previous scan when we use a non-MVCC snapshot, so we must + * re-establish the lineoff <= PageGetMaxOffsetNumber(dp) + * invariant + */ lineoff = /* previous offnum */ - OffsetNumberPrev(ItemPointerGetOffsetNumber(&(tuple->t_self))); + Min(lines, + OffsetNumberPrev(ItemPointerGetOffsetNumber(&(tuple->t_self)))); } /* page and lineoff now reference the physically previous tid */ @@ -678,6 +685,13 @@ heapgettup(HeapScanDesc scan, lpp = PageGetItemId(dp, lineoff); for (;;) { + /* + * Only continue scanning the page while we have lines left. + * + * Note that this protects us from accessing line pointers past + * PageGetMaxOffsetNumber(); both for forward scans when we resume the + * table scan, and for when we start scanning a new page. + */ while (linesleft > 0) { if (ItemIdIsNormal(lpp)) @@ -8556,10 +8570,8 @@ heap_xlog_vacuum(XLogReaderState *record) ItemIdSetUnused(lp); } - /* - * Update the page's hint bit about whether it has free pointers - */ - PageSetHasFreeLinePointers(page); + /* Attempt to truncate line pointer array now */ + PageTruncateLinePointerArray(page); PageSetLSN(page, lsn); MarkBufferDirty(buffer); |