Skip to content

Commit ad57c2a

Browse files
committed
Optimize check_search_path() by using SearchPathCache.
A hash lookup is faster than re-validating the string, particularly because we use SplitIdentifierString() for validation. Important when search_path changes frequently. Discussion: https://postgr.es/m/04c8592dbd694e4114a3ed87139a7a04e4363030.camel%40j-davis.com
1 parent 8efa301 commit ad57c2a

File tree

1 file changed

+54
-2
lines changed

1 file changed

+54
-2
lines changed

src/backend/catalog/namespace.c

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
235235
* when a function has search_path set in proconfig. Add a search path cache
236236
* that can be used by recomputeNamespacePath().
237237
*
238+
* The cache is also used to remember already-validated strings in
239+
* check_search_path() to avoid the need to call SplitIdentifierString()
240+
* repeatedly.
241+
*
238242
* The search path cache is based on a wrapper around a simplehash hash table
239243
* (nsphash, defined below). The spcache wrapper deals with OOM while trying
240244
* to initialize a key, and also offers a more convenient API.
@@ -296,6 +300,21 @@ spcache_init(void)
296300
searchPathCacheValid = true;
297301
}
298302

303+
/*
304+
* Look up entry in search path cache without inserting. Returns NULL if not
305+
* present.
306+
*/
307+
static SearchPathCacheEntry *
308+
spcache_lookup(const char *searchPath, Oid roleid)
309+
{
310+
SearchPathCacheKey cachekey = {
311+
.searchPath = searchPath,
312+
.roleid = roleid
313+
};
314+
315+
return nsphash_lookup(SearchPathCache, cachekey);
316+
}
317+
299318
/*
300319
* Look up or insert entry in search path cache.
301320
*
@@ -4578,11 +4597,40 @@ ResetTempTableNamespace(void)
45784597
bool
45794598
check_search_path(char **newval, void **extra, GucSource source)
45804599
{
4600+
Oid roleid = InvalidOid;
4601+
const char *searchPath = *newval;
45814602
char *rawname;
45824603
List *namelist;
4604+
bool use_cache = (SearchPathCacheContext != NULL);
45834605

4584-
/* Need a modifiable copy of string */
4585-
rawname = pstrdup(*newval);
4606+
/*
4607+
* We used to try to check that the named schemas exist, but there are
4608+
* many valid use-cases for having search_path settings that include
4609+
* schemas that don't exist; and often, we are not inside a transaction
4610+
* here and so can't consult the system catalogs anyway. So now, the only
4611+
* requirement is syntactic validity of the identifier list.
4612+
*/
4613+
4614+
/*
4615+
* Checking only the syntactic validity also allows us to use the search
4616+
* path cache (if available) to avoid calling SplitIdentifierString() on
4617+
* the same string repeatedly.
4618+
*/
4619+
if (use_cache)
4620+
{
4621+
spcache_init();
4622+
4623+
roleid = GetUserId();
4624+
4625+
if (spcache_lookup(searchPath, roleid) != NULL)
4626+
return true;
4627+
}
4628+
4629+
/*
4630+
* Ensure validity check succeeds before creating cache entry.
4631+
*/
4632+
4633+
rawname = pstrdup(searchPath); /* need a modifiable copy */
45864634

45874635
/* Parse string into list of identifiers */
45884636
if (!SplitIdentifierString(rawname, ',', &namelist))
@@ -4605,6 +4653,10 @@ check_search_path(char **newval, void **extra, GucSource source)
46054653
pfree(rawname);
46064654
list_free(namelist);
46074655

4656+
/* create empty cache entry */
4657+
if (use_cache)
4658+
(void) spcache_insert(searchPath, roleid);
4659+
46084660
return true;
46094661
}
46104662

0 commit comments

Comments
 (0)