From 8e2e2662214a0a6d0fb23a070ea78d691d8ced43 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Thu, 31 Oct 2024 10:02:58 +0200 Subject: [PATCH] Simplify call to rebuild relcache entry for indexes RelationClearRelation(rebuild == true) calls RelationReloadIndexInfo() for indexes. We can rely on that in RelationIdGetRelation(), instead of calling RelationReloadIndexInfo() directly. That simplifies the code a little. In the passing, add a comment in RelationBuildLocalRelation() explaining why it doesn't call RelationInitIndexAccessInfo(). It's because at index creation, it's called before the pg_index row has been created. That's also the reason that RelationClearRelation() still needs a special case to go through the full-blown rebuild if the index support information in the relcache entry hasn't been populated yet. Reviewed-by: jian he Discussion: https://www.postgresql.org/message-id/9c9e8908-7b3e-4ce7-85a8-00c0e165a3d6%40iki.fi --- src/backend/utils/cache/relcache.c | 41 +++++++++++++----------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index c326f687eb..8143f08043 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -2083,16 +2083,7 @@ RelationIdGetRelation(Oid relationId) /* revalidate cache entry if necessary */ if (!rd->rd_isvalid) { - /* - * Indexes only have a limited number of possible schema changes, - * and we don't want to use the full-blown procedure because it's - * a headache for indexes that reload itself depends on. - */ - if (rd->rd_rel->relkind == RELKIND_INDEX || - rd->rd_rel->relkind == RELKIND_PARTITIONED_INDEX) - RelationReloadIndexInfo(rd); - else - RelationClearRelation(rd, true); + RelationClearRelation(rd, true); /* * Normally entries need to be valid here, but before the relcache @@ -2264,14 +2255,6 @@ RelationReloadIndexInfo(Relation relation) !relation->rd_isvalid && relation->rd_droppedSubid == InvalidSubTransactionId); - /* Ensure it's closed at smgr level */ - RelationCloseSmgr(relation); - - /* Must free any AM cached data upon relcache flush */ - if (relation->rd_amcache) - pfree(relation->rd_amcache); - relation->rd_amcache = NULL; - /* * If it's a shared index, we might be called before backend startup has * finished selecting a database, in which case we have no way to read @@ -2600,15 +2583,19 @@ RelationClearRelation(Relation relation, bool rebuild) return; /* - * Even non-system indexes should not be blown away if they are open and - * have valid index support information. This avoids problems with active - * use of the index support information. As with nailed indexes, we - * re-read the pg_class row to handle possible physical relocation of the - * index, and we check for pg_index updates too. + * Indexes only have a limited number of possible schema changes, and we + * don't want to use the full-blown procedure because it's a headache for + * indexes that reload itself depends on. + * + * As an exception, use the full procedure if the index access info hasn't + * been initialized yet. Index creation relies on that: it first builds + * the relcache entry with RelationBuildLocalRelation(), creates the + * pg_index tuple only after that, and then relies on + * CommandCounterIncrement to load the pg_index contents. */ if ((relation->rd_rel->relkind == RELKIND_INDEX || relation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX) && - relation->rd_refcnt > 0 && + rebuild && relation->rd_indexcxt != NULL) { if (IsTransactionState()) @@ -3720,6 +3707,12 @@ RelationBuildLocalRelation(const char *relname, if (RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_SEQUENCE) RelationInitTableAccessMethod(rel); + /* + * Leave index access method uninitialized, because the pg_index row has + * not been inserted at this stage of index creation yet. The cache + * invalidation after pg_index row has been inserted will initialize it. + */ + /* * Okay to insert into the relcache hash table. *