diff options
author | Tomas Vondra <tomas.vondra@postgresql.org> | 2022-06-16 15:02:48 +0200 |
---|---|---|
committer | Tomas Vondra <tomas.vondra@postgresql.org> | 2022-06-16 15:02:49 +0200 |
commit | e3fcca0d0d2414f3a50d6fd40eddf48b7df81475 (patch) | |
tree | 6c1793031fd174af93149a23450e3e3b5299bdb4 /src/backend | |
parent | 664da2a389e5d1d4ebf0f98c82997739cd496e8e (diff) | |
download | postgresql-e3fcca0d0d2414f3a50d6fd40eddf48b7df81475.tar.gz postgresql-e3fcca0d0d2414f3a50d6fd40eddf48b7df81475.zip |
Revert changes in HOT handling of BRIN indexes
This reverts commits 5753d4ee32 and fe60b67250 that modified HOT to
ignore BRIN indexes. The commit message for 5753d4ee32 claims that:
When determining whether an index update may be skipped by using
HOT, we can ignore attributes indexed only by BRIN indexes. There
are no index pointers to individual tuples in BRIN, and the page
range summary will be updated anyway as it relies on visibility
info.
This is partially incorrect - it's true BRIN indexes don't point to
individual tuples, so HOT chains are not an issue, but the visibitlity
info is not sufficient to keep the index up to date. This can easily
result in corrupted indexes, as demonstrated in the hackers thread.
This does not mean relaxing the HOT restrictions for BRIN is a lost
cause, but it needs to handle the two aspects (allowing HOT chains and
updating the page range summaries) as separate. But that requires a
major changes, and it's too late for that in the current dev cycle.
Reported-by: Tomas Vondra
Discussion: https://postgr.es/m/05ebcb44-f383-86e3-4f31-0a97a55634cf@enterprisedb.com
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/access/brin/brin.c | 1 | ||||
-rw-r--r-- | src/backend/access/gin/ginutil.c | 1 | ||||
-rw-r--r-- | src/backend/access/gist/gist.c | 1 | ||||
-rw-r--r-- | src/backend/access/hash/hash.c | 1 | ||||
-rw-r--r-- | src/backend/access/heap/heapam.c | 2 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtree.c | 1 | ||||
-rw-r--r-- | src/backend/access/spgist/spgutils.c | 1 | ||||
-rw-r--r-- | src/backend/utils/cache/relcache.c | 53 |
8 files changed, 24 insertions, 37 deletions
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c index 0de1441dc6d..e88f7efa7e4 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -108,7 +108,6 @@ brinhandler(PG_FUNCTION_ARGS) amroutine->amcanparallel = false; amroutine->amcaninclude = false; amroutine->amusemaintenanceworkmem = false; - amroutine->amhotblocking = false; amroutine->amparallelvacuumoptions = VACUUM_OPTION_PARALLEL_CLEANUP; amroutine->amkeytype = InvalidOid; diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c index 3d15701a01e..20f470648be 100644 --- a/src/backend/access/gin/ginutil.c +++ b/src/backend/access/gin/ginutil.c @@ -56,7 +56,6 @@ ginhandler(PG_FUNCTION_ARGS) amroutine->amcanparallel = false; amroutine->amcaninclude = false; amroutine->amusemaintenanceworkmem = true; - amroutine->amhotblocking = true; amroutine->amparallelvacuumoptions = VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_CLEANUP; amroutine->amkeytype = InvalidOid; diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index 8c6c744ab74..5866c6aaaf7 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -78,7 +78,6 @@ gisthandler(PG_FUNCTION_ARGS) amroutine->amcanparallel = false; amroutine->amcaninclude = true; amroutine->amusemaintenanceworkmem = false; - amroutine->amhotblocking = true; amroutine->amparallelvacuumoptions = VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_COND_CLEANUP; amroutine->amkeytype = InvalidOid; diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index fd1a7119b6c..c361509d68d 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -75,7 +75,6 @@ hashhandler(PG_FUNCTION_ARGS) amroutine->amcanparallel = false; amroutine->amcaninclude = false; amroutine->amusemaintenanceworkmem = false; - amroutine->amhotblocking = true; amroutine->amparallelvacuumoptions = VACUUM_OPTION_PARALLEL_BULKDEL; amroutine->amkeytype = INT4OID; diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 74218510276..637de1116c9 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -3190,7 +3190,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup, * Note that we get copies of each bitmap, so we need not worry about * relcache flush happening midway through. */ - hot_attrs = RelationGetIndexAttrBitmap(relation, INDEX_ATTR_BITMAP_HOT_BLOCKING); + hot_attrs = RelationGetIndexAttrBitmap(relation, INDEX_ATTR_BITMAP_ALL); key_attrs = RelationGetIndexAttrBitmap(relation, INDEX_ATTR_BITMAP_KEY); id_attrs = RelationGetIndexAttrBitmap(relation, INDEX_ATTR_BITMAP_IDENTITY_KEY); diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 06131f23d4b..9b730f303fb 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -114,7 +114,6 @@ bthandler(PG_FUNCTION_ARGS) amroutine->amcanparallel = true; amroutine->amcaninclude = true; amroutine->amusemaintenanceworkmem = false; - amroutine->amhotblocking = true; amroutine->amparallelvacuumoptions = VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_COND_CLEANUP; amroutine->amkeytype = InvalidOid; diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c index a171ca8a08a..2c661fcf96f 100644 --- a/src/backend/access/spgist/spgutils.c +++ b/src/backend/access/spgist/spgutils.c @@ -62,7 +62,6 @@ spghandler(PG_FUNCTION_ARGS) amroutine->amcanparallel = false; amroutine->amcaninclude = true; amroutine->amusemaintenanceworkmem = false; - amroutine->amhotblocking = true; amroutine->amparallelvacuumoptions = VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_COND_CLEANUP; amroutine->amkeytype = InvalidOid; diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 60e72f9e8bf..0e8fda97f86 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -2439,10 +2439,10 @@ RelationDestroyRelation(Relation relation, bool remember_tupdesc) list_free_deep(relation->rd_fkeylist); list_free(relation->rd_indexlist); list_free(relation->rd_statlist); + bms_free(relation->rd_indexattr); bms_free(relation->rd_keyattr); bms_free(relation->rd_pkattr); bms_free(relation->rd_idattr); - bms_free(relation->rd_hotblockingattr); if (relation->rd_pubdesc) pfree(relation->rd_pubdesc); if (relation->rd_options) @@ -5104,10 +5104,10 @@ RelationGetIndexPredicate(Relation relation) Bitmapset * RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind) { + Bitmapset *indexattrs; /* indexed columns */ Bitmapset *uindexattrs; /* columns in unique indexes */ Bitmapset *pkindexattrs; /* columns in the primary index */ Bitmapset *idindexattrs; /* columns in the replica identity */ - Bitmapset *hotblockingattrs; /* columns with HOT blocking indexes */ List *indexoidlist; List *newindexoidlist; Oid relpkindex; @@ -5116,18 +5116,18 @@ RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind) MemoryContext oldcxt; /* Quick exit if we already computed the result. */ - if (relation->rd_attrsvalid) + if (relation->rd_indexattr != NULL) { switch (attrKind) { + case INDEX_ATTR_BITMAP_ALL: + return bms_copy(relation->rd_indexattr); case INDEX_ATTR_BITMAP_KEY: return bms_copy(relation->rd_keyattr); case INDEX_ATTR_BITMAP_PRIMARY_KEY: return bms_copy(relation->rd_pkattr); case INDEX_ATTR_BITMAP_IDENTITY_KEY: return bms_copy(relation->rd_idattr); - case INDEX_ATTR_BITMAP_HOT_BLOCKING: - return bms_copy(relation->rd_hotblockingattr); default: elog(ERROR, "unknown attrKind %u", attrKind); } @@ -5158,7 +5158,7 @@ restart: relreplindex = relation->rd_replidindex; /* - * For each index, add referenced attributes to appropriate bitmaps. + * For each index, add referenced attributes to indexattrs. * * Note: we consider all indexes returned by RelationGetIndexList, even if * they are not indisready or indisvalid. This is important because an @@ -5167,10 +5167,10 @@ restart: * CONCURRENTLY is far enough along that we should ignore the index, it * won't be returned at all by RelationGetIndexList. */ + indexattrs = NULL; uindexattrs = NULL; pkindexattrs = NULL; idindexattrs = NULL; - hotblockingattrs = NULL; foreach(l, indexoidlist) { Oid indexOid = lfirst_oid(l); @@ -5235,9 +5235,8 @@ restart: */ if (attrnum != 0) { - if (indexDesc->rd_indam->amhotblocking) - hotblockingattrs = bms_add_member(hotblockingattrs, - attrnum - FirstLowInvalidHeapAttributeNumber); + indexattrs = bms_add_member(indexattrs, + attrnum - FirstLowInvalidHeapAttributeNumber); if (isKey && i < indexDesc->rd_index->indnkeyatts) uindexattrs = bms_add_member(uindexattrs, @@ -5254,15 +5253,10 @@ restart: } /* Collect all attributes used in expressions, too */ - if (indexDesc->rd_indam->amhotblocking) - pull_varattnos(indexExpressions, 1, &hotblockingattrs); + pull_varattnos(indexExpressions, 1, &indexattrs); - /* - * Collect all attributes in the index predicate, too. We have to - * ignore amhotblocking flag, because the row might become indexable, - * in which case we have to add it to the index. - */ - pull_varattnos(indexPredicate, 1, &hotblockingattrs); + /* Collect all attributes in the index predicate, too */ + pull_varattnos(indexPredicate, 1, &indexattrs); index_close(indexDesc, AccessShareLock); } @@ -5290,46 +5284,46 @@ restart: bms_free(uindexattrs); bms_free(pkindexattrs); bms_free(idindexattrs); - bms_free(hotblockingattrs); + bms_free(indexattrs); goto restart; } /* Don't leak the old values of these bitmaps, if any */ + bms_free(relation->rd_indexattr); + relation->rd_indexattr = NULL; bms_free(relation->rd_keyattr); relation->rd_keyattr = NULL; bms_free(relation->rd_pkattr); relation->rd_pkattr = NULL; bms_free(relation->rd_idattr); relation->rd_idattr = NULL; - bms_free(relation->rd_hotblockingattr); - relation->rd_hotblockingattr = NULL; /* * Now save copies of the bitmaps in the relcache entry. We intentionally - * set rd_attrsvalid last, because that's what signals validity of the - * values; if we run out of memory before making that copy, we won't leave - * the relcache entry looking like the other ones are valid but empty. + * set rd_indexattr last, because that's the one that signals validity of + * the values; if we run out of memory before making that copy, we won't + * leave the relcache entry looking like the other ones are valid but + * empty. */ oldcxt = MemoryContextSwitchTo(CacheMemoryContext); relation->rd_keyattr = bms_copy(uindexattrs); relation->rd_pkattr = bms_copy(pkindexattrs); relation->rd_idattr = bms_copy(idindexattrs); - relation->rd_hotblockingattr = bms_copy(hotblockingattrs); - relation->rd_attrsvalid = true; + relation->rd_indexattr = bms_copy(indexattrs); MemoryContextSwitchTo(oldcxt); /* We return our original working copy for caller to play with */ switch (attrKind) { + case INDEX_ATTR_BITMAP_ALL: + return indexattrs; case INDEX_ATTR_BITMAP_KEY: return uindexattrs; case INDEX_ATTR_BITMAP_PRIMARY_KEY: return pkindexattrs; case INDEX_ATTR_BITMAP_IDENTITY_KEY: return idindexattrs; - case INDEX_ATTR_BITMAP_HOT_BLOCKING: - return hotblockingattrs; default: elog(ERROR, "unknown attrKind %u", attrKind); return NULL; @@ -6250,11 +6244,10 @@ load_relcache_init_file(bool shared) rel->rd_indexlist = NIL; rel->rd_pkindex = InvalidOid; rel->rd_replidindex = InvalidOid; - rel->rd_attrsvalid = false; + rel->rd_indexattr = NULL; rel->rd_keyattr = NULL; rel->rd_pkattr = NULL; rel->rd_idattr = NULL; - rel->rd_hotblockingattr = NULL; rel->rd_pubdesc = NULL; rel->rd_statvalid = false; rel->rd_statlist = NIL; |