From 96e518ea22886702fa58eacdbf1cb1f8eedf290e Mon Sep 17 00:00:00 2001 From: Matthias van de Meent Date: Tue, 18 May 2021 20:18:12 +0200 Subject: [PATCH v6] Improve usage of line pointer array truncation in heapam. This will allow reuse of what is effectively free space for data as well as new line pointers, instead of keeping it reserved for line pointers only. It further improves efficiency of HeapAM's local updates by not requiring a 2nd run of VACUUM to come by before we can reuse line pointers left over from temporarily long HOT chains. Additionally, it improves the current application of line pointer truncation truncate down to 0 line pointers; improving page applicability for PageIsEmpty()-based optimizations and making empty heap pages applicable for MaxHeapTupleSize-sized tuple insertions on 32-bit systems. --- src/backend/storage/page/bufpage.c | 33 +++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/backend/storage/page/bufpage.c b/src/backend/storage/page/bufpage.c index 82ca91f597..3c9fc2bf34 100644 --- a/src/backend/storage/page/bufpage.c +++ b/src/backend/storage/page/bufpage.c @@ -688,10 +688,13 @@ compactify_tuples(itemIdCompact itemidbase, int nitems, Page page, bool presorte * * This routine is usable for heap pages only, but see PageIndexMultiDelete. * - * Never removes unused line pointers. PageTruncateLinePointerArray can - * safely remove some unused line pointers. It ought to be safe for this - * routine to free unused line pointers in roughly the same way, but it's not - * clear that that would be beneficial. + * Also removes line pointers, similar to PageTruncateLinePointerArray. + * The main benefit for also truncating the line pointer array here is that + * now HOT workloads can also benefit from this optimization. The remaining + * line pointers from a temporary increase in HOT chain length on this page + * will now be cleaned up as well, even if no logical tuple is ever deleted + * from the page. This allows for more extended use of local updates, + * without needing to wait for a second run of VACUUM: * * PageTruncateLinePointerArray is only called during VACUUM's second pass * over the heap. Any unused line pointers that it sees are likely to have @@ -718,6 +721,7 @@ PageRepairFragmentation(Page page) int nline, nstorage, nunused; + OffsetNumber lastUsed = InvalidOffsetNumber; int i; Size totallen; bool presorted = true; /* For now */ @@ -751,6 +755,7 @@ PageRepairFragmentation(Page page) lp = PageGetItemId(page, i); if (ItemIdIsUsed(lp)) { + lastUsed = i; if (ItemIdHasStorage(lp)) { itemidptr->offsetindex = i - 1; @@ -798,6 +803,19 @@ PageRepairFragmentation(Page page) compactify_tuples(itemidbase, nstorage, page, presorted); } + /* The last line pointer is not the last used line pointer */ + if (lastUsed != nline) + { + int nunusedend = nline - lastUsed; + + Assert(nunused >= nunusedend && nunusedend > 0); + + /* remove trailing unused line pointers from the count */ + nunused -= nunusedend; + /* truncate the line pointer array */ + ((PageHeader) page)->pd_lower -= (sizeof(ItemIdData) * nunusedend); + } + /* Set hint bit for PageAddItemExtended */ if (nunused > 0) PageSetHasFreeLinePointers(page); @@ -815,11 +833,6 @@ PageRepairFragmentation(Page page) * pointer on the page (if VACUUM didn't have an LP_DEAD item on the page that * it just set to LP_UNUSED then it should not call here). * - * We avoid truncating the line pointer array to 0 items, if necessary by - * leaving behind a single remaining LP_UNUSED item. This is a little - * arbitrary, but it seems like a good idea to avoid leaving a PageIsEmpty() - * page behind. - * * Caller can have either an exclusive lock or a super-exclusive lock on * page's buffer. The page's PD_HAS_FREE_LINES hint bit will be set or unset * based on whether or not we leave behind any remaining LP_UNUSED items. @@ -837,7 +850,7 @@ PageTruncateLinePointerArray(Page page) { ItemId lp = PageGetItemId(page, i); - if (!countdone && i > FirstOffsetNumber) + if (!countdone) { /* * Still determining which line pointers from the end of the array -- 2.20.1