解决分区数多时优化器阶段判断部分分区usable属性性能问题
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
||||
|
||||
26
src/common/backend/utils/cache/partcache.cpp
vendored
26
src/common/backend/utils/cache/partcache.cpp
vendored
@ -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;
|
||||
}
|
||||
14
src/common/backend/utils/cache/relcache.cpp
vendored
14
src/common/backend/utils/cache/relcache.cpp
vendored
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user