Merge pull request #5192 from citusdata/use-pg-functions

Use relcache utils instead of scanning catalog tables for indexes and ext stats
pull/5195/head
Onur Tirtir 2021-08-18 17:56:56 +03:00 committed by GitHub
commit 262f89359e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 61 additions and 140 deletions

View File

@ -888,17 +888,12 @@ GetIndexAccessMethodName(Oid indexId)
Oid indexAMId = indexForm->relam; Oid indexAMId = indexForm->relam;
ReleaseSysCache(indexTuple); ReleaseSysCache(indexTuple);
/* fetch pg_am tuple of index' access method */ char *indexAmName = get_am_name(indexAMId);
HeapTuple indexAMTuple = SearchSysCache1(AMOID, ObjectIdGetDatum(indexAMId)); if (!indexAmName)
if (!HeapTupleIsValid(indexAMTuple))
{ {
ereport(ERROR, (errmsg("access method with oid %u does not exist", indexAMId))); ereport(ERROR, (errmsg("access method with oid %u does not exist", indexAMId)));
} }
Form_pg_am indexAMForm = (Form_pg_am) GETSTRUCT(indexAMTuple);
char *indexAmName = pstrdup(indexAMForm->amname.data);
ReleaseSysCache(indexAMTuple);
return indexAmName; return indexAmName;
} }

View File

@ -69,6 +69,9 @@ static char * GetRenameShardTriggerCommand(Oid shardRelationId, char *triggerNam
static void DropRelationTruncateTriggers(Oid relationId); static void DropRelationTruncateTriggers(Oid relationId);
static char * GetDropTriggerCommand(Oid relationId, char *triggerName); static char * GetDropTriggerCommand(Oid relationId, char *triggerName);
static List * GetRenameStatsCommandList(List *statsOidList, uint64 shardId); static List * GetRenameStatsCommandList(List *statsOidList, uint64 shardId);
static void AppendExplicitIndexIdsToList(Form_pg_index indexForm,
List **explicitIndexIdList,
int flags);
static void DropDefaultExpressionsAndMoveOwnedSequenceOwnerships(Oid sourceRelationId, static void DropDefaultExpressionsAndMoveOwnedSequenceOwnerships(Oid sourceRelationId,
Oid targetRelationId); Oid targetRelationId);
static void DropDefaultColumnDefinition(Oid relationId, char *columnName); static void DropDefaultColumnDefinition(Oid relationId, char *columnName);
@ -684,7 +687,10 @@ GetRenameShardIndexCommand(Oid indexOid, uint64 shardId)
static void static void
RenameShardRelationStatistics(Oid shardRelationId, uint64 shardId) RenameShardRelationStatistics(Oid shardRelationId, uint64 shardId)
{ {
List *statsOidList = GetExplicitStatisticsIdList(shardRelationId); Relation shardRelation = RelationIdGetRelation(shardRelationId);
List *statsOidList = RelationGetStatExtList(shardRelation);
RelationClose(shardRelation);
List *statsCommandList = GetRenameStatsCommandList(statsOidList, shardId); List *statsCommandList = GetRenameStatsCommandList(statsOidList, shardId);
char *command = NULL; char *command = NULL;
@ -834,51 +840,25 @@ GetDropTriggerCommand(Oid relationId, char *triggerName)
List * List *
GetExplicitIndexOidList(Oid relationId) GetExplicitIndexOidList(Oid relationId)
{ {
int scanKeyCount = 1; /* flags are not applicable for AppendExplicitIndexIdsToList */
ScanKeyData scanKey[1]; int flags = 0;
return ExecuteFunctionOnEachTableIndex(relationId, AppendExplicitIndexIdsToList,
flags);
}
PushOverrideEmptySearchPath(CurrentMemoryContext);
Relation pgIndex = table_open(IndexRelationId, AccessShareLock); /*
* AppendExplicitIndexIdsToList adds the given index oid if it is
ScanKeyInit(&scanKey[0], Anum_pg_index_indrelid, * explicitly created on its relation.
BTEqualStrategyNumber, F_OIDEQ, relationId); */
static void
bool useIndex = true; AppendExplicitIndexIdsToList(Form_pg_index indexForm, List **explicitIndexIdList,
SysScanDesc scanDescriptor = systable_beginscan(pgIndex, IndexIndrelidIndexId, int flags)
useIndex, NULL, scanKeyCount, {
scanKey); if (!IndexImpliedByAConstraint(indexForm))
List *indexOidList = NIL;
HeapTuple heapTuple = systable_getnext(scanDescriptor);
while (HeapTupleIsValid(heapTuple))
{ {
Form_pg_index indexForm = (Form_pg_index) GETSTRUCT(heapTuple); *explicitIndexIdList = lappend_oid(*explicitIndexIdList, indexForm->indexrelid);
Oid indexId = indexForm->indexrelid;
bool indexImpliedByConstraint = IndexImpliedByAConstraint(indexForm);
/*
* Skip the indexes that are not implied by explicitly executing
* a CREATE INDEX command.
*/
if (!indexImpliedByConstraint)
{
indexOidList = lappend_oid(indexOidList, indexId);
}
heapTuple = systable_getnext(scanDescriptor);
} }
systable_endscan(scanDescriptor);
table_close(pgIndex, NoLock);
/* revert back to original search_path */
PopOverrideSearchPath();
return indexOidList;
} }

View File

@ -306,37 +306,25 @@ ExecuteFunctionOnEachTableIndex(Oid relationId, PGIndexProcessor pgIndexProcesso
int indexFlags) int indexFlags)
{ {
List *result = NIL; List *result = NIL;
ScanKeyData scanKey[1];
int scanKeyCount = 1;
PushOverrideEmptySearchPath(CurrentMemoryContext); Relation relation = RelationIdGetRelation(relationId);
List *indexIdList = RelationGetIndexList(relation);
/* open system catalog and scan all indexes that belong to this table */ Oid indexId = InvalidOid;
Relation pgIndex = table_open(IndexRelationId, AccessShareLock); foreach_oid(indexId, indexIdList)
ScanKeyInit(&scanKey[0], Anum_pg_index_indrelid,
BTEqualStrategyNumber, F_OIDEQ, relationId);
SysScanDesc scanDescriptor = systable_beginscan(pgIndex,
IndexIndrelidIndexId, true, /* indexOK */
NULL, scanKeyCount, scanKey);
HeapTuple heapTuple = systable_getnext(scanDescriptor);
while (HeapTupleIsValid(heapTuple))
{ {
Form_pg_index indexForm = (Form_pg_index) GETSTRUCT(heapTuple); HeapTuple indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
pgIndexProcessor(indexForm, &result, indexFlags); if (!HeapTupleIsValid(indexTuple))
{
ereport(ERROR, (errmsg("cache lookup failed for index with oid %u",
indexId)));
}
heapTuple = systable_getnext(scanDescriptor); Form_pg_index indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
pgIndexProcessor(indexForm, &result, indexFlags);
ReleaseSysCache(indexTuple);
} }
/* clean up scan and close system catalog */ RelationClose(relation);
systable_endscan(scanDescriptor);
table_close(pgIndex, AccessShareLock);
/* revert back to original search_path */
PopOverrideSearchPath();
return result; return result;
} }

View File

@ -425,16 +425,18 @@ PreprocessAlterStatisticsOwnerStmt(Node *node, const char *queryString,
* GetExplicitStatisticsCommandList returns the list of DDL commands to create * GetExplicitStatisticsCommandList returns the list of DDL commands to create
* or alter statistics that are explicitly created for the table with relationId. * or alter statistics that are explicitly created for the table with relationId.
* This function gets called when distributing the table with relationId. * This function gets called when distributing the table with relationId.
* See comment of GetExplicitStatisticsIdList function.
*/ */
List * List *
GetExplicitStatisticsCommandList(Oid relationId) GetExplicitStatisticsCommandList(Oid relationId)
{ {
List *explicitStatisticsCommandList = NIL; List *explicitStatisticsCommandList = NIL;
PushOverrideEmptySearchPath(CurrentMemoryContext); Relation relation = RelationIdGetRelation(relationId);
List *statisticsIdList = RelationGetStatExtList(relation);
RelationClose(relation);
List *statisticsIdList = GetExplicitStatisticsIdList(relationId); /* generate fully-qualified names */
PushOverrideEmptySearchPath(CurrentMemoryContext);
Oid statisticsId = InvalidOid; Oid statisticsId = InvalidOid;
foreach_oid(statisticsId, statisticsIdList) foreach_oid(statisticsId, statisticsIdList)
@ -488,23 +490,19 @@ GetExplicitStatisticsSchemaIdList(Oid relationId)
{ {
List *schemaIdList = NIL; List *schemaIdList = NIL;
Relation pgStatistics = table_open(StatisticExtRelationId, AccessShareLock); Relation relation = RelationIdGetRelation(relationId);
List *statsIdList = RelationGetStatExtList(relation);
RelationClose(relation);
int scanKeyCount = 1; Oid statsId = InvalidOid;
ScanKeyData scanKey[1]; foreach_oid(statsId, statsIdList)
ScanKeyInit(&scanKey[0], Anum_pg_statistic_ext_stxrelid,
BTEqualStrategyNumber, F_OIDEQ, relationId);
bool useIndex = true;
SysScanDesc scanDescriptor = systable_beginscan(pgStatistics,
StatisticExtRelidIndexId,
useIndex, NULL, scanKeyCount,
scanKey);
HeapTuple heapTuple = systable_getnext(scanDescriptor);
while (HeapTupleIsValid(heapTuple))
{ {
HeapTuple heapTuple = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statsId));
if (!HeapTupleIsValid(heapTuple))
{
ereport(ERROR, (errmsg("cache lookup failed for statistics "
"object with oid %u", statsId)));
}
FormData_pg_statistic_ext *statisticsForm = FormData_pg_statistic_ext *statisticsForm =
(FormData_pg_statistic_ext *) GETSTRUCT(heapTuple); (FormData_pg_statistic_ext *) GETSTRUCT(heapTuple);
@ -513,12 +511,9 @@ GetExplicitStatisticsSchemaIdList(Oid relationId)
{ {
schemaIdList = lappend_oid(schemaIdList, schemaId); schemaIdList = lappend_oid(schemaIdList, schemaId);
} }
ReleaseSysCache(heapTuple);
heapTuple = systable_getnext(scanDescriptor);
} }
systable_endscan(scanDescriptor);
table_close(pgStatistics, NoLock);
return schemaIdList; return schemaIdList;
} }
@ -567,48 +562,6 @@ GetAlterIndexStatisticsCommands(Oid indexOid)
} }
/*
* GetExplicitStatisticsIdList returns a list of OIDs corresponding to the statistics
* that are explicitly created on the relation with relationId. That means,
* this function discards internal statistics implicitly created by postgres.
*/
List *
GetExplicitStatisticsIdList(Oid relationId)
{
List *statisticsIdList = NIL;
Relation pgStatistics = table_open(StatisticExtRelationId, AccessShareLock);
int scanKeyCount = 1;
ScanKeyData scanKey[1];
ScanKeyInit(&scanKey[0], Anum_pg_statistic_ext_stxrelid,
BTEqualStrategyNumber, F_OIDEQ, relationId);
bool useIndex = true;
SysScanDesc scanDescriptor = systable_beginscan(pgStatistics,
StatisticExtRelidIndexId,
useIndex, NULL, scanKeyCount,
scanKey);
HeapTuple heapTuple = systable_getnext(scanDescriptor);
while (HeapTupleIsValid(heapTuple))
{
FormData_pg_statistic_ext *statisticsForm =
(FormData_pg_statistic_ext *) GETSTRUCT(heapTuple);
Oid statisticsId = statisticsForm->oid;
statisticsIdList = lappend_oid(statisticsIdList, statisticsId);
heapTuple = systable_getnext(scanDescriptor);
}
systable_endscan(scanDescriptor);
table_close(pgStatistics, NoLock);
return statisticsIdList;
}
/* /*
* GenerateAlterIndexColumnSetStatsCommand returns a string in form of 'ALTER INDEX .. * GenerateAlterIndexColumnSetStatsCommand returns a string in form of 'ALTER INDEX ..
* ALTER COLUMN .. SET STATISTICS ..' which will be used to create a DDL command to * ALTER COLUMN .. SET STATISTICS ..' which will be used to create a DDL command to

View File

@ -798,6 +798,9 @@ void
GatherIndexAndConstraintDefinitionList(Form_pg_index indexForm, List **indexDDLEventList, GatherIndexAndConstraintDefinitionList(Form_pg_index indexForm, List **indexDDLEventList,
int indexFlags) int indexFlags)
{ {
/* generate fully-qualified names */
PushOverrideEmptySearchPath(CurrentMemoryContext);
Oid indexId = indexForm->indexrelid; Oid indexId = indexForm->indexrelid;
bool indexImpliedByConstraint = IndexImpliedByAConstraint(indexForm); bool indexImpliedByConstraint = IndexImpliedByAConstraint(indexForm);
@ -845,6 +848,9 @@ GatherIndexAndConstraintDefinitionList(Form_pg_index indexForm, List **indexDDLE
*indexDDLEventList = list_concat(*indexDDLEventList, *indexDDLEventList = list_concat(*indexDDLEventList,
alterIndexStatisticsCommands); alterIndexStatisticsCommands);
} }
/* revert back to original search_path */
PopOverrideSearchPath();
} }

View File

@ -388,7 +388,6 @@ extern List * PreprocessAlterStatisticsOwnerStmt(Node *node, const char *querySt
extern List * GetExplicitStatisticsCommandList(Oid relationId); extern List * GetExplicitStatisticsCommandList(Oid relationId);
extern List * GetExplicitStatisticsSchemaIdList(Oid relationId); extern List * GetExplicitStatisticsSchemaIdList(Oid relationId);
extern List * GetAlterIndexStatisticsCommands(Oid indexOid); extern List * GetAlterIndexStatisticsCommands(Oid indexOid);
extern List * GetExplicitStatisticsIdList(Oid relationId);
/* subscription.c - forward declarations */ /* subscription.c - forward declarations */
extern Node * ProcessCreateSubscriptionStmt(CreateSubscriptionStmt *createSubStmt); extern Node * ProcessCreateSubscriptionStmt(CreateSubscriptionStmt *createSubStmt);