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.
 	 *