From 9921a637e370cebeee0cc5129522ceb5bddf51b0 Mon Sep 17 00:00:00 2001 From: David Christensen Date: Wed, 7 Feb 2024 10:49:31 -0500 Subject: [PATCH v2 3/4] Split MaxIndexTuplesPerPage into runtime and max values --- contrib/amcheck/verify_nbtree.c | 6 +++--- src/backend/access/gist/gist.c | 2 +- src/backend/access/gist/gistget.c | 8 ++++---- src/backend/access/hash/hash.c | 4 ++-- src/backend/access/hash/hashovfl.c | 6 +++--- src/backend/access/hash/hashpage.c | 4 ++-- src/backend/access/hash/hashsearch.c | 10 +++++----- src/backend/access/nbtree/nbtinsert.c | 2 +- src/backend/access/nbtree/nbtpage.c | 8 ++++---- src/backend/access/nbtree/nbtree.c | 4 ++-- src/backend/access/nbtree/nbtxlog.c | 4 ++-- src/backend/access/spgist/spgdoinsert.c | 2 +- src/backend/access/spgist/spgscan.c | 2 +- src/backend/access/spgist/spgvacuum.c | 22 +++++++++++----------- src/backend/storage/page/bufpage.c | 6 +++--- src/include/access/hash.h | 2 +- src/include/access/itup.h | 23 ++++++++++++++++------- src/include/access/nbtree.h | 2 +- src/include/access/spgist_private.h | 12 ++++++------ 19 files changed, 69 insertions(+), 60 deletions(-) diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c index 1ef4cff88e..b1089693be 100644 --- a/contrib/amcheck/verify_nbtree.c +++ b/contrib/amcheck/verify_nbtree.c @@ -3447,12 +3447,12 @@ palloc_btree_page(BtreeCheckState *state, BlockNumber blocknum) * to move left, in the case of backward index scans). */ maxoffset = PageGetMaxOffsetNumber(page); - if (maxoffset > MaxIndexTuplesPerPage) + if (maxoffset > ClusterMaxIndexTuplesPerPage) ereport(ERROR, (errcode(ERRCODE_INDEX_CORRUPTED), - errmsg("Number of items on block %u of index \"%s\" exceeds MaxIndexTuplesPerPage (%u)", + errmsg("Number of items on block %u of index \"%s\" exceeds ClusterMaxIndexTuplesPerPage (%u)", blocknum, RelationGetRelationName(state->rel), - MaxIndexTuplesPerPage))); + ClusterMaxIndexTuplesPerPage))); if (!P_ISLEAF(opaque) && !P_ISDELETED(opaque) && maxoffset < P_FIRSTDATAKEY(opaque)) ereport(ERROR, diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index ed4ffa63a7..c2f1762c36 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -1663,7 +1663,7 @@ freeGISTstate(GISTSTATE *giststate) static void gistprunepage(Relation rel, Page page, Buffer buffer, Relation heapRel) { - OffsetNumber deletable[MaxIndexTuplesPerPage]; + OffsetNumber deletable[MaxIndexTuplesPerPageLimit]; int ndeletable = 0; OffsetNumber offnum, maxoff; diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c index b35b8a9757..32443a7047 100644 --- a/src/backend/access/gist/gistget.c +++ b/src/backend/access/gist/gistget.c @@ -658,12 +658,12 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir) MemoryContextSwitchTo(so->giststate->scanCxt); so->killedItems = - (OffsetNumber *) palloc(MaxIndexTuplesPerPage + (OffsetNumber *) palloc(ClusterMaxIndexTuplesPerPage * sizeof(OffsetNumber)); MemoryContextSwitchTo(oldCxt); } - if (so->numKilled < MaxIndexTuplesPerPage) + if (so->numKilled < ClusterMaxIndexTuplesPerPage) so->killedItems[so->numKilled++] = so->pageData[so->curPageData - 1].offnum; } @@ -695,12 +695,12 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir) MemoryContextSwitchTo(so->giststate->scanCxt); so->killedItems = - (OffsetNumber *) palloc(MaxIndexTuplesPerPage + (OffsetNumber *) palloc(ClusterMaxIndexTuplesPerPage * sizeof(OffsetNumber)); MemoryContextSwitchTo(oldCxt); } - if (so->numKilled < MaxIndexTuplesPerPage) + if (so->numKilled < ClusterMaxIndexTuplesPerPage) so->killedItems[so->numKilled++] = so->pageData[so->curPageData - 1].offnum; } diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index 01d06b7c32..210371ce25 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -312,9 +312,9 @@ hashgettuple(IndexScanDesc scan, ScanDirection dir) */ if (so->killedItems == NULL) so->killedItems = (int *) - palloc(MaxIndexTuplesPerPage * sizeof(int)); + palloc(ClusterMaxIndexTuplesPerPage * sizeof(int)); - if (so->numKilled < MaxIndexTuplesPerPage) + if (so->numKilled < ClusterMaxIndexTuplesPerPage) so->killedItems[so->numKilled++] = so->currPos.itemIndex; } diff --git a/src/backend/access/hash/hashovfl.c b/src/backend/access/hash/hashovfl.c index c280ae885e..ec3a1a8356 100644 --- a/src/backend/access/hash/hashovfl.c +++ b/src/backend/access/hash/hashovfl.c @@ -903,9 +903,9 @@ _hash_squeezebucket(Relation rel, OffsetNumber roffnum; OffsetNumber maxroffnum; OffsetNumber deletable[MaxOffsetNumber]; - IndexTuple itups[MaxIndexTuplesPerPage]; - Size tups_size[MaxIndexTuplesPerPage]; - OffsetNumber itup_offsets[MaxIndexTuplesPerPage]; + IndexTuple itups[MaxIndexTuplesPerPageLimit]; + Size tups_size[MaxIndexTuplesPerPageLimit]; + OffsetNumber itup_offsets[MaxIndexTuplesPerPageLimit]; uint16 ndeletable = 0; uint16 nitups = 0; Size all_tups_size = 0; diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c index d09c349e28..314c7f557b 100644 --- a/src/backend/access/hash/hashpage.c +++ b/src/backend/access/hash/hashpage.c @@ -1087,8 +1087,8 @@ _hash_splitbucket(Relation rel, Page npage; HashPageOpaque oopaque; HashPageOpaque nopaque; - OffsetNumber itup_offsets[MaxIndexTuplesPerPage]; - IndexTuple itups[MaxIndexTuplesPerPage]; + OffsetNumber itup_offsets[MaxIndexTuplesPerPageLimit]; + IndexTuple itups[MaxIndexTuplesPerPageLimit]; Size all_tups_size = 0; int i; uint16 nitups = 0; diff --git a/src/backend/access/hash/hashsearch.c b/src/backend/access/hash/hashsearch.c index 0d99d6abc8..785bd953ea 100644 --- a/src/backend/access/hash/hashsearch.c +++ b/src/backend/access/hash/hashsearch.c @@ -532,7 +532,7 @@ _hash_readpage(IndexScanDesc scan, Buffer *bufP, ScanDirection dir) itemIndex = _hash_load_qualified_items(scan, page, offnum, dir); - if (itemIndex != MaxIndexTuplesPerPage) + if (itemIndex != ClusterMaxIndexTuplesPerPage) break; /* @@ -571,8 +571,8 @@ _hash_readpage(IndexScanDesc scan, Buffer *bufP, ScanDirection dir) } so->currPos.firstItem = itemIndex; - so->currPos.lastItem = MaxIndexTuplesPerPage - 1; - so->currPos.itemIndex = MaxIndexTuplesPerPage - 1; + so->currPos.lastItem = ClusterMaxIndexTuplesPerPage - 1; + so->currPos.itemIndex = ClusterMaxIndexTuplesPerPage - 1; } if (so->currPos.buf == so->hashso_bucket_buf || @@ -652,13 +652,13 @@ _hash_load_qualified_items(IndexScanDesc scan, Page page, offnum = OffsetNumberNext(offnum); } - Assert(itemIndex <= MaxIndexTuplesPerPage); + Assert(itemIndex <= ClusterMaxIndexTuplesPerPage); return itemIndex; } else { /* load items[] in descending order */ - itemIndex = MaxIndexTuplesPerPage; + itemIndex = ClusterMaxIndexTuplesPerPage; while (offnum >= FirstOffsetNumber) { diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index 7e8902e48c..711b7afff3 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -2685,7 +2685,7 @@ _bt_delete_or_dedup_one_page(Relation rel, Relation heapRel, bool simpleonly, bool checkingunique, bool uniquedup, bool indexUnchanged) { - OffsetNumber deletable[MaxIndexTuplesPerPage]; + OffsetNumber deletable[MaxIndexTuplesPerPageLimit]; int ndeletable = 0; OffsetNumber offnum, minoff, diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c index 01bbece6bf..f728b36c80 100644 --- a/src/backend/access/nbtree/nbtpage.c +++ b/src/backend/access/nbtree/nbtpage.c @@ -1160,7 +1160,7 @@ _bt_delitems_vacuum(Relation rel, Buffer buf, bool needswal = RelationNeedsWAL(rel); char *updatedbuf = NULL; Size updatedbuflen = 0; - OffsetNumber updatedoffsets[MaxIndexTuplesPerPage]; + OffsetNumber updatedoffsets[MaxIndexTuplesPerPageLimit]; /* Shouldn't be called unless there's something to do */ Assert(ndeletable > 0 || nupdatable > 0); @@ -1291,7 +1291,7 @@ _bt_delitems_delete(Relation rel, Buffer buf, bool needswal = RelationNeedsWAL(rel); char *updatedbuf = NULL; Size updatedbuflen = 0; - OffsetNumber updatedoffsets[MaxIndexTuplesPerPage]; + OffsetNumber updatedoffsets[MaxIndexTuplesPerPageLimit]; /* Shouldn't be called unless there's something to do */ Assert(ndeletable > 0 || nupdatable > 0); @@ -1519,8 +1519,8 @@ _bt_delitems_delete_check(Relation rel, Buffer buf, Relation heapRel, OffsetNumber postingidxoffnum = InvalidOffsetNumber; int ndeletable = 0, nupdatable = 0; - OffsetNumber deletable[MaxIndexTuplesPerPage]; - BTVacuumPosting updatable[MaxIndexTuplesPerPage]; + OffsetNumber deletable[MaxIndexTuplesPerPageLimit]; + BTVacuumPosting updatable[MaxIndexTuplesPerPageLimit]; /* Use tableam interface to determine which tuples to delete first */ snapshotConflictHorizon = table_index_delete_tuples(heapRel, delstate); diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 41df1027d2..55bd14fecd 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -1142,9 +1142,9 @@ backtrack: } else if (P_ISLEAF(opaque)) { - OffsetNumber deletable[MaxIndexTuplesPerPage]; + OffsetNumber deletable[MaxIndexTuplesPerPageLimit]; int ndeletable; - BTVacuumPosting updatable[MaxIndexTuplesPerPage]; + BTVacuumPosting updatable[MaxIndexTuplesPerPageLimit]; int nupdatable; OffsetNumber offnum, minoff, diff --git a/src/backend/access/nbtree/nbtxlog.c b/src/backend/access/nbtree/nbtxlog.c index b5b0e22447..c912260d2c 100644 --- a/src/backend/access/nbtree/nbtxlog.c +++ b/src/backend/access/nbtree/nbtxlog.c @@ -38,8 +38,8 @@ _bt_restore_page(Page page, char *from, int len) IndexTupleData itupdata; Size itemsz; char *end = from + len; - Item items[MaxIndexTuplesPerPage]; - uint16 itemsizes[MaxIndexTuplesPerPage]; + Item items[MaxIndexTuplesPerPageLimit]; + uint16 itemsizes[MaxIndexTuplesPerPageLimit]; int i; int nitems; diff --git a/src/backend/access/spgist/spgdoinsert.c b/src/backend/access/spgist/spgdoinsert.c index a4995c168b..3c3ede6f3a 100644 --- a/src/backend/access/spgist/spgdoinsert.c +++ b/src/backend/access/spgist/spgdoinsert.c @@ -134,7 +134,7 @@ spgPageIndexMultiDelete(SpGistState *state, Page page, BlockNumber blkno, OffsetNumber offnum) { OffsetNumber firstItem; - OffsetNumber sortednos[MaxIndexTuplesPerPage]; + OffsetNumber sortednos[MaxIndexTuplesPerPageLimit]; SpGistDeadTuple tuple = NULL; int i; diff --git a/src/backend/access/spgist/spgscan.c b/src/backend/access/spgist/spgscan.c index 03293a7816..5690fc4981 100644 --- a/src/backend/access/spgist/spgscan.c +++ b/src/backend/access/spgist/spgscan.c @@ -961,7 +961,7 @@ storeGettuple(SpGistScanOpaque so, ItemPointer heapPtr, SpGistLeafTuple leafTuple, bool recheck, bool recheckDistances, double *nonNullDistances) { - Assert(so->nPtrs < MaxIndexTuplesPerPage); + Assert(so->nPtrs < ClusterMaxIndexTuplesPerPage); so->heapPtrs[so->nPtrs] = *heapPtr; so->recheck[so->nPtrs] = recheck; so->recheckDistances[so->nPtrs] = recheckDistances; diff --git a/src/backend/access/spgist/spgvacuum.c b/src/backend/access/spgist/spgvacuum.c index d2e1624924..586f367b50 100644 --- a/src/backend/access/spgist/spgvacuum.c +++ b/src/backend/access/spgist/spgvacuum.c @@ -127,14 +127,14 @@ vacuumLeafPage(spgBulkDeleteState *bds, Relation index, Buffer buffer, { Page page = BufferGetPage(buffer); spgxlogVacuumLeaf xlrec; - OffsetNumber toDead[MaxIndexTuplesPerPage]; - OffsetNumber toPlaceholder[MaxIndexTuplesPerPage]; - OffsetNumber moveSrc[MaxIndexTuplesPerPage]; - OffsetNumber moveDest[MaxIndexTuplesPerPage]; - OffsetNumber chainSrc[MaxIndexTuplesPerPage]; - OffsetNumber chainDest[MaxIndexTuplesPerPage]; - OffsetNumber predecessor[MaxIndexTuplesPerPage + 1]; - bool deletable[MaxIndexTuplesPerPage + 1]; + OffsetNumber toDead[MaxIndexTuplesPerPageLimit]; + OffsetNumber toPlaceholder[MaxIndexTuplesPerPageLimit]; + OffsetNumber moveSrc[MaxIndexTuplesPerPageLimit]; + OffsetNumber moveDest[MaxIndexTuplesPerPageLimit]; + OffsetNumber chainSrc[MaxIndexTuplesPerPageLimit]; + OffsetNumber chainDest[MaxIndexTuplesPerPageLimit]; + OffsetNumber predecessor[MaxIndexTuplesPerPageLimit + 1]; + bool deletable[MaxIndexTuplesPerPageLimit + 1]; int nDeletable; OffsetNumber i, max = PageGetMaxOffsetNumber(page); @@ -407,7 +407,7 @@ vacuumLeafRoot(spgBulkDeleteState *bds, Relation index, Buffer buffer) { Page page = BufferGetPage(buffer); spgxlogVacuumRoot xlrec; - OffsetNumber toDelete[MaxIndexTuplesPerPage]; + OffsetNumber toDelete[MaxIndexTuplesPerPageLimit]; OffsetNumber i, max = PageGetMaxOffsetNumber(page); @@ -497,8 +497,8 @@ vacuumRedirectAndPlaceholder(Relation index, Relation heaprel, Buffer buffer) firstPlaceholder = InvalidOffsetNumber; bool hasNonPlaceholder = false; bool hasUpdate = false; - OffsetNumber itemToPlaceholder[MaxIndexTuplesPerPage]; - OffsetNumber itemnos[MaxIndexTuplesPerPage]; + OffsetNumber itemToPlaceholder[MaxIndexTuplesPerPageLimit]; + OffsetNumber itemnos[MaxIndexTuplesPerPageLimit]; spgxlogVacuumRedirect xlrec; GlobalVisState *vistest; diff --git a/src/backend/storage/page/bufpage.c b/src/backend/storage/page/bufpage.c index f78efce9ad..bc37eae9f2 100644 --- a/src/backend/storage/page/bufpage.c +++ b/src/backend/storage/page/bufpage.c @@ -1165,8 +1165,8 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems) Offset pd_upper = phdr->pd_upper; Offset pd_special = phdr->pd_special; Offset last_offset; - itemIdCompactData itemidbase[MaxIndexTuplesPerPage]; - ItemIdData newitemids[MaxIndexTuplesPerPage]; + itemIdCompactData itemidbase[MaxIndexTuplesPerPageLimit]; + ItemIdData newitemids[MaxIndexTuplesPerPageLimit]; itemIdCompact itemidptr; ItemId lp; int nline, @@ -1178,7 +1178,7 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems) OffsetNumber offnum; bool presorted = true; /* For now */ - Assert(nitems <= MaxIndexTuplesPerPage); + Assert(nitems <= ClusterMaxIndexTuplesPerPage); /* * If there aren't very many items to delete, then retail diff --git a/src/include/access/hash.h b/src/include/access/hash.h index 9c7d81525b..b797872bd4 100644 --- a/src/include/access/hash.h +++ b/src/include/access/hash.h @@ -124,7 +124,7 @@ typedef struct HashScanPosData int lastItem; /* last valid index in items[] */ int itemIndex; /* current index in items[] */ - HashScanPosItem items[MaxIndexTuplesPerPage]; /* MUST BE LAST */ + HashScanPosItem items[MaxIndexTuplesPerPageLimit]; /* MUST BE LAST */ } HashScanPosData; #define HashScanPosIsPinned(scanpos) \ diff --git a/src/include/access/itup.h b/src/include/access/itup.h index 94885751e5..61fa8ff538 100644 --- a/src/include/access/itup.h +++ b/src/include/access/itup.h @@ -148,11 +148,19 @@ index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull) #endif /* - * MaxIndexTuplesPerPage is an upper bound on the number of tuples that can - * fit on one index page. An index tuple must have either data or a null - * bitmap, so we can safely assume it's at least 1 byte bigger than a bare - * IndexTupleData struct. We arrive at the divisor because each tuple - * must be maxaligned, and it must have an associated line pointer. + * ClusterMaxIndexTuplesPerPage is a cluster-specific upper bound on the + * number of tuples that can fit on one index page. An index tuple must have + * either data or a null bitmap, so we can safely assume it's at least 1 byte + * bigger than a bare IndexTupleData struct. We arrive at the divisor because + * each tuple must be maxaligned, and it must have an associated line pointer. + * + * MaxIndexTuplesPerPageLimit is the largest value that + * ClusterMaxIndexTuplesPerPage could be. While these currently evaluate to + * the same value, these are being split out so ClusterMaxIndexTuplesPerPage + * can become a variable instead of a constant. + * + * The CalcMaxIndexTuplesPerPage() macro is used to determine the appropriate + * values, given the usable page space on a given page. * * To be index-type-independent, this does not account for any special space * on the page, and is thus conservative. @@ -163,8 +171,9 @@ index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull) * estimated here, seemingly allowing one more tuple than estimated here. * But such a page always has at least MAXALIGN special space, so we're safe. */ -#define MaxIndexTuplesPerPage \ - ((int) ((BLCKSZ - SizeOfPageHeaderData) / \ +#define CalcMaxIndexTuplesPerPage(size) ((int) ((size) / \ (MAXALIGN(sizeof(IndexTupleData) + 1) + sizeof(ItemIdData)))) +#define ClusterMaxIndexTuplesPerPage CalcMaxIndexTuplesPerPage(BLCKSZ - SizeOfPageHeaderData) +#define MaxIndexTuplesPerPageLimit CalcMaxIndexTuplesPerPage(BLCKSZ - SizeOfPageHeaderData) #endif /* ITUP_H */ diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 6eb162052e..676fa5e0a9 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -887,7 +887,7 @@ typedef struct BTDedupStateData * are implicitly unchanged by deduplication pass). */ int nintervals; /* current number of intervals in array */ - BTDedupInterval intervals[MaxIndexTuplesPerPage]; + BTDedupInterval intervals[MaxIndexTuplesPerPageLimit]; } BTDedupStateData; typedef BTDedupStateData *BTDedupState; diff --git a/src/include/access/spgist_private.h b/src/include/access/spgist_private.h index 2e9c757b30..d8ca2b7e0f 100644 --- a/src/include/access/spgist_private.h +++ b/src/include/access/spgist_private.h @@ -226,17 +226,17 @@ typedef struct SpGistScanOpaqueData TupleDesc reconTupDesc; /* if so, descriptor for reconstructed tuples */ int nPtrs; /* number of TIDs found on current page */ int iPtr; /* index for scanning through same */ - ItemPointerData heapPtrs[MaxIndexTuplesPerPage]; /* TIDs from cur page */ - bool recheck[MaxIndexTuplesPerPage]; /* their recheck flags */ - bool recheckDistances[MaxIndexTuplesPerPage]; /* distance recheck + ItemPointerData heapPtrs[MaxIndexTuplesPerPageLimit]; /* TIDs from cur page */ + bool recheck[MaxIndexTuplesPerPageLimit]; /* their recheck flags */ + bool recheckDistances[MaxIndexTuplesPerPageLimit]; /* distance recheck * flags */ - HeapTuple reconTups[MaxIndexTuplesPerPage]; /* reconstructed tuples */ + HeapTuple reconTups[MaxIndexTuplesPerPageLimit]; /* reconstructed tuples */ /* distances (for recheck) */ - IndexOrderByDistance *distances[MaxIndexTuplesPerPage]; + IndexOrderByDistance *distances[MaxIndexTuplesPerPageLimit]; /* - * Note: using MaxIndexTuplesPerPage above is a bit hokey since + * Note: using ClusterMaxIndexTuplesPerPage above is a bit hokey since * SpGistLeafTuples aren't exactly IndexTuples; however, they are larger, * so this is safe. */ -- 2.40.1