diff --git a/src/common/backend/utils/cache/knl_globaltabdefcache.cpp b/src/common/backend/utils/cache/knl_globaltabdefcache.cpp index 813f4ea81..69dcf2b3e 100644 --- a/src/common/backend/utils/cache/knl_globaltabdefcache.cpp +++ b/src/common/backend/utils/cache/knl_globaltabdefcache.cpp @@ -500,6 +500,7 @@ Relation CopyRelationData(Relation newrel, Relation rel, MemoryContext rules_cxt newrel->sliceMap = CopyRelationSliceMap(rel); newrel->entry = NULL; + newrel->rd_ind_partition_all_usable = rel->rd_ind_partition_all_usable; return newrel; } diff --git a/src/common/backend/utils/cache/partcache.cpp b/src/common/backend/utils/cache/partcache.cpp index cb4fe44bd..d4ae7ffbe 100644 --- a/src/common/backend/utils/cache/partcache.cpp +++ b/src/common/backend/utils/cache/partcache.cpp @@ -2418,3 +2418,29 @@ bool PartitionMetadataDisabledClean(Relation pgPartition) } return result; } + +bool PartCheckPartitionedIndexAllUsable(Relation index_relation) +{ + Assert(index_relation->rd_index != NULL); + Oid indrelid = index_relation->rd_index->indrelid; + Relation relation = relation_open(indrelid, NoLock); + if (relation->storage_type == SEGMENT_PAGE) { + relation_close(relation, NoLock); + return false; + } + relation_close(relation, NoLock); + Assert(RelationIsPartitioned(index_relation) && RelationIsIndex(index_relation)); + bool result = true; + List* partitions = indexGetPartitionList(index_relation, AccessShareLock); + ListCell* lc = NULL; + foreach(lc, partitions) { + Partition index_partition = (Partition)lfirst(lc); + if (!index_partition->pd_part->indisusable) { + result = false; + break; + } + } + releasePartitionList(index_relation, &partitions, AccessShareLock); + list_free_ext(partitions); + return result; +} \ No newline at end of file diff --git a/src/common/backend/utils/cache/relcache.cpp b/src/common/backend/utils/cache/relcache.cpp index 3a84ed576..9852e027e 100755 --- a/src/common/backend/utils/cache/relcache.cpp +++ b/src/common/backend/utils/cache/relcache.cpp @@ -2823,6 +2823,13 @@ void RelationInitIndexAccessInfo(Relation relation, HeapTuple index_tuple) relation->rd_exclstrats = NULL; relation->rd_amcache = NULL; relation->rd_rootcache = InvalidBuffer; + + /* check usability status if partitioned index */ + if (RelationIsPartitioned(relation)) { + relation->rd_ind_partition_all_usable = PartCheckPartitionedIndexAllUsable(relation); + } else { + relation->rd_ind_partition_all_usable = true; /* trivial for non-partitioned index */ + } } /* @@ -3513,6 +3520,13 @@ void RelationReloadIndexInfo(Relation relation) ReleaseSysCache(tuple); } + /* check usability status if partitioned index */ + if (RelationIsPartitioned(relation)) { + relation->rd_ind_partition_all_usable = PartCheckPartitionedIndexAllUsable(relation); + } else { + relation->rd_ind_partition_all_usable = true; /* trivial for non-partitioned index */ + } + /* Okay, now it's valid again */ relation->rd_isvalid = true; } diff --git a/src/gausskernel/optimizer/commands/tablecmds.cpp b/src/gausskernel/optimizer/commands/tablecmds.cpp index a0a2e5348..c1c319763 100755 --- a/src/gausskernel/optimizer/commands/tablecmds.cpp +++ b/src/gausskernel/optimizer/commands/tablecmds.cpp @@ -24798,6 +24798,8 @@ static void ATExecUnusableIndexPartition(Relation rel, const char* partition_nam AccessExclusiveLock); // lock on heap partition // call the internal function ATExecSetIndexUsableState(PartitionRelationId, indexPartOid, false); + /* Invoke cache invalidation to refresh index relation data */ + CacheInvalidateRelcache(rel); } static void ATUnusableGlobalIndex(Relation rel) @@ -24910,6 +24912,8 @@ static void ATExecUnusableAllIndexOnPartition(Relation rel, const char* partitio // close index and it's partition partitionClose(parentIndex, indexPart, NoLock); index_close(parentIndex, NoLock); + /* Invoke cache invalidation to refresh index relation data */ + CacheInvalidateRelcacheByRelid(parentIndId); } freePartList(partIndexlist); diff --git a/src/gausskernel/optimizer/util/subpartitionpruning.cpp b/src/gausskernel/optimizer/util/subpartitionpruning.cpp index 095504e18..f52480616 100644 --- a/src/gausskernel/optimizer/util/subpartitionpruning.cpp +++ b/src/gausskernel/optimizer/util/subpartitionpruning.cpp @@ -205,9 +205,14 @@ bool checkPartitionIndexUnusable(Oid indexOid, int partItrs, PruningResult* prun /* cannot lock heap in case deadlock, we need process invalid messages here */ AcceptInvalidationMessages(); + indexRel = relation_open(indexOid, NoLock); + if (indexRel->rd_ind_partition_all_usable) { + relation_close(indexRel, NoLock); + return true; + } + heapRelOid = IndexGetRelation(indexOid, false); heapRel = relation_open(heapRelOid, NoLock); - indexRel = relation_open(indexOid, NoLock); if (RelationIsGlobalIndex(indexRel)) { partitionIndexUnusable = indexRel->rd_index->indisusable; relation_close(heapRel, NoLock); @@ -594,6 +599,12 @@ IndexesUsableType eliminate_partition_index_unusable(Oid indexOid, PruningResult return ret; } + if (indexRel->rd_ind_partition_all_usable) { + relation_close(heapRel, NoLock); + relation_close(indexRel, NoLock); + return INDEXES_FULL_USABLE; + } + if (!RelationIsPartitioned(heapRel) || !RelationIsPartitioned(indexRel)) { ereport(ERROR, (errmodule(MOD_OPT), errcode(ERRCODE_OPTIMIZER_INCONSISTENT_STATE), diff --git a/src/include/utils/partcache.h b/src/include/utils/partcache.h index e908b6680..55a041783 100644 --- a/src/include/utils/partcache.h +++ b/src/include/utils/partcache.h @@ -106,5 +106,6 @@ extern void PartitionSetAllEnabledClean(Oid parentOid); extern void PartitionGetAllInvisibleParts(Oid parentOid, OidRBTree** invisibleParts); extern bool PartitionMetadataDisabledClean(Relation pgPartition); extern void UpdateWaitCleanGpiRelOptions(Relation pgPartition, HeapTuple partTuple, bool enable, bool inplace); +extern bool PartCheckPartitionedIndexAllUsable(Relation indexRelation); #endif /* RELCACHE_H */ diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index 6422d613c..aee44544d 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -232,6 +232,7 @@ typedef struct RelationData { void* rd_amcache; /* available for use by index AM */ Oid* rd_indcollation; /* OIDs of index collations */ Buffer rd_rootcache; /* for root caching */ + bool rd_ind_partition_all_usable; /* * foreign-table support