Hi,

The commit
https://github.com/postgres/postgres/commit/b17ff07aa3eb142d2cde2ea00e4a4e8f63686f96
Introduced the CopyStatistics function.

To do the work, CopyStatistics uses a less efficient function
to update/insert tuples at catalog systems.

The comment at indexing.c says:
"Avoid using it for multiple tuples, since opening the indexes
 * and building the index info structures is moderately expensive.
 * (Use CatalogTupleInsertWithInfo in such cases.)"

So inspired by the comment, changed in some fews places,
the CatalogInsert/CatalogUpdate to more efficient functions
CatalogInsertWithInfo/CatalogUpdateWithInfo.

With quick tests, resulting in small performance.

head:

1. REINDEX TABLE CONCURRENTLY pgbench_accounts;
Time: 77,805 ms
Time: 74,836 ms
Time: 73,480 ms

2. REINDEX TABLE CONCURRENTLY pgbench_tellers;
Time: 22,260 ms
Time: 22,205 ms
Time: 21,008 ms

patched:

1. REINDEX TABLE CONCURRENTLY pgbench_accounts;
Time: 65,048 ms
Time: 61,853 ms
Time: 61,119 ms

2. REINDEX TABLE CONCURRENTLY pgbench_tellers;
Time: 15,999 ms
Time: 15,961 ms
Time: 13,264 ms

There are other places that this could be useful,
but a careful analysis is necessary.

regards,
Ranier Vilela
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 9b03579e6e..cf15051a05 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -2856,8 +2856,7 @@ CopyStatistics(Oid fromrelid, Oid torelid)
 	SysScanDesc scan;
 	ScanKeyData key[1];
 	Relation	statrel;
-
-	statrel = table_open(StatisticRelationId, RowExclusiveLock);
+	CatalogIndexState indstate;
 
 	/* Now search for stat records */
 	ScanKeyInit(&key[0],
@@ -2865,6 +2864,9 @@ CopyStatistics(Oid fromrelid, Oid torelid)
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(fromrelid));
 
+	statrel = table_open(StatisticRelationId, RowExclusiveLock);
+	indstate = CatalogOpenIndexes(statrel);
+
 	scan = systable_beginscan(statrel, StatisticRelidAttnumInhIndexId,
 							  true, NULL, 1, key);
 
@@ -2878,13 +2880,14 @@ CopyStatistics(Oid fromrelid, Oid torelid)
 
 		/* update the copy of the tuple and insert it */
 		statform->starelid = torelid;
-		CatalogTupleInsert(statrel, tup);
+		CatalogTupleInsertWithInfo(statrel, tup, indstate);
 
 		heap_freetuple(tup);
 	}
 
 	systable_endscan(scan);
 
+	CatalogCloseIndexes(indstate);
 	table_close(statrel, RowExclusiveLock);
 }
 
diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
index 114715498d..785fbc1669 100644
--- a/src/backend/catalog/pg_enum.c
+++ b/src/backend/catalog/pg_enum.c
@@ -69,6 +69,7 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
 	bool		nulls[Natts_pg_enum];
 	ListCell   *lc;
 	HeapTuple	tup;
+	CatalogIndexState indstate;
 
 	num_elems = list_length(vals);
 
@@ -113,6 +114,9 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
 	/* and make the entries */
 	memset(nulls, false, sizeof(nulls));
 
+	/* open the Catalog Indexes for Insert Tuples */
+	indstate = CatalogOpenIndexes(pg_enum);
+
 	elemno = 0;
 	foreach(lc, vals)
 	{
@@ -137,7 +141,7 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
 
 		tup = heap_form_tuple(RelationGetDescr(pg_enum), values, nulls);
 
-		CatalogTupleInsert(pg_enum, tup);
+		CatalogTupleInsertWithInfo(pg_enum, tup, indstate);
 		heap_freetuple(tup);
 
 		elemno++;
@@ -145,6 +149,7 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
 
 	/* clean up */
 	pfree(oids);
+	CatalogCloseIndexes(indstate);
 	table_close(pg_enum, RowExclusiveLock);
 }
 
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index a7966fff83..5cfcdf8ba7 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -1624,12 +1624,14 @@ static void
 update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
 {
 	Relation	sd;
+	CatalogIndexState indstate;
 	int			attno;
 
 	if (natts <= 0)
 		return;					/* nothing to do */
 
 	sd = table_open(StatisticRelationId, RowExclusiveLock);
+	indstate = CatalogOpenIndexes(sd);
 
 	for (attno = 0; attno < natts; attno++)
 	{
@@ -1735,18 +1737,19 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
 									 nulls,
 									 replaces);
 			ReleaseSysCache(oldtup);
-			CatalogTupleUpdate(sd, &stup->t_self, stup);
+			CatalogTupleUpdateWithInfo(sd, &stup->t_self, stup, indstate);
 		}
 		else
 		{
 			/* No, insert new tuple */
 			stup = heap_form_tuple(RelationGetDescr(sd), values, nulls);
-			CatalogTupleInsert(sd, stup);
+			CatalogTupleInsertWithInfo(sd, stup, indstate);
 		}
 
 		heap_freetuple(stup);
 	}
 
+	CatalogCloseIndexes(indstate);
 	table_close(sd, RowExclusiveLock);
 }
 
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index 4cc4e3c00f..b95b989c5a 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -1004,14 +1004,16 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied)
 		ScanKeyData skey;
 		SysScanDesc scan;
 		HeapTuple	maptup;
-
-		mapRel = table_open(TSConfigMapRelationId, RowExclusiveLock);
+		CatalogIndexState indstate;
 
 		ScanKeyInit(&skey,
 					Anum_pg_ts_config_map_mapcfg,
 					BTEqualStrategyNumber, F_OIDEQ,
 					ObjectIdGetDatum(sourceOid));
 
+		mapRel = table_open(TSConfigMapRelationId, RowExclusiveLock);
+		indstate = CatalogOpenIndexes(mapRel);
+
 		scan = systable_beginscan(mapRel, TSConfigMapIndexId, true,
 								  NULL, 1, &skey);
 
@@ -1032,12 +1034,14 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied)
 
 			newmaptup = heap_form_tuple(mapRel->rd_att, mapvalues, mapnulls);
 
-			CatalogTupleInsert(mapRel, newmaptup);
+			CatalogTupleInsertWithInfo(mapRel, newmaptup, indstate);
 
 			heap_freetuple(newmaptup);
 		}
 
 		systable_endscan(scan);
+
+		CatalogCloseIndexes(indstate);
 	}
 
 	address = makeConfigurationDependencies(tup, false, mapRel);
@@ -1225,6 +1229,7 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt,
 	Oid		   *dictIds;
 	int			ndict;
 	ListCell   *c;
+	CatalogIndexState indstate;
 
 	tsform = (Form_pg_ts_config) GETSTRUCT(tup);
 	cfgId = tsform->oid;
@@ -1275,6 +1280,9 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt,
 		i++;
 	}
 
+	/* open the Catalog Indexes for Update/Insert Tuples */
+	indstate = CatalogOpenIndexes(relMap);
+
 	if (stmt->replace)
 	{
 		/*
@@ -1334,7 +1342,7 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt,
 				newtup = heap_modify_tuple(maptup,
 										   RelationGetDescr(relMap),
 										   repl_val, repl_null, repl_repl);
-				CatalogTupleUpdate(relMap, &newtup->t_self, newtup);
+				CatalogTupleUpdateWithInfo(relMap, &newtup->t_self, newtup, indstate);
 			}
 		}
 
@@ -1359,12 +1367,13 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt,
 				values[Anum_pg_ts_config_map_mapdict - 1] = ObjectIdGetDatum(dictIds[j]);
 
 				tup = heap_form_tuple(relMap->rd_att, values, nulls);
-				CatalogTupleInsert(relMap, tup);
+				CatalogTupleInsertWithInfo(relMap, tup, indstate);
 
 				heap_freetuple(tup);
 			}
 		}
 	}
+	CatalogCloseIndexes(indstate);
 
 	EventTriggerCollectAlterTSConfig(stmt, cfgId, dictIds, ndict);
 }
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 265a48af7e..f9521bc1dd 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -1551,6 +1551,7 @@ AddRoleMems(const char *rolename, Oid roleid,
 {
 	Relation	pg_authmem_rel;
 	TupleDesc	pg_authmem_dsc;
+	CatalogIndexState indstate;
 	ListCell   *specitem;
 	ListCell   *iditem;
 	Oid			currentUserId = GetUserId();
@@ -1718,6 +1719,9 @@ AddRoleMems(const char *rolename, Oid roleid,
 		ReleaseSysCacheList(memlist);
 	}
 
+	/* open the Catalog Indexes for Update/Insert Tuples */
+	indstate = CatalogOpenIndexes(pg_authmem_rel);
+
 	/* Now perform the catalog updates. */
 	forboth(specitem, memberSpecs, iditem, memberIds)
 	{
@@ -1789,7 +1793,7 @@ AddRoleMems(const char *rolename, Oid roleid,
 			tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
 									  new_record,
 									  new_record_nulls, new_record_repl);
-			CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple);
+			CatalogTupleUpdateWithInfo(pg_authmem_rel, &tuple->t_self, tuple, indstate);
 
 			ReleaseSysCache(authmem_tuple);
 		}
@@ -1829,7 +1833,7 @@ AddRoleMems(const char *rolename, Oid roleid,
 			new_record[Anum_pg_auth_members_oid - 1] = objectId;
 			tuple = heap_form_tuple(pg_authmem_dsc,
 									new_record, new_record_nulls);
-			CatalogTupleInsert(pg_authmem_rel, tuple);
+			CatalogTupleInsertWithInfo(pg_authmem_rel, tuple, indstate);
 
 			/* updateAclDependencies wants to pfree array inputs */
 			newmembers[0] = grantorId;
@@ -1842,6 +1846,7 @@ AddRoleMems(const char *rolename, Oid roleid,
 		/* CCI after each change, in case there are duplicates in list */
 		CommandCounterIncrement();
 	}
+	CatalogCloseIndexes(indstate);
 
 	/*
 	 * Close pg_authmem, but keep lock till commit.

Reply via email to