The other thing that emerged from
http://www.postgresql.org/message-id/flat/CAOR=d=3j1U_q-zf8+jUx1hkx8ps+N8pm=EUTqyFdJ5ov=+fawg@mail.gmail.com
is that for workloads like this, OverrideSearchPathMatchesCurrent is
a bottleneck: it's part of the code path needed to re-use a cached plan,
and this example is doing a lot of that. The original implementation
of that function followed the KISS principle, since I thought it probably
wouldn't be a bottleneck. Now that that's proven wrong, I offer the
attached reimplementation, which saves about 9% of overall runtime on
Scott's example by avoiding palloc/pfree traffic. It knows a lot more
about the relation of override search paths to active search paths than
it did before; but the adjacent functions know these things too, so it
doesn't seem like much of a loss from a maintainability standpoint.
regards, tom lane
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 911f015..7a06332 100644
*** a/src/backend/catalog/namespace.c
--- b/src/backend/catalog/namespace.c
*************** CopyOverrideSearchPath(OverrideSearchPat
*** 3145,3164 ****
bool
OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
{
! /* Easiest way to do this is GetOverrideSearchPath() and compare */
! bool result;
! OverrideSearchPath *cur;
! cur = GetOverrideSearchPath(CurrentMemoryContext);
! if (path->addCatalog == cur->addCatalog &&
! path->addTemp == cur->addTemp &&
! equal(path->schemas, cur->schemas))
! result = true;
! else
! result = false;
! list_free(cur->schemas);
! pfree(cur);
! return result;
}
/*
--- 3145,3188 ----
bool
OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
{
! ListCell *lc,
! *lcp;
! recomputeNamespacePath();
!
! /* We scan down the activeSearchPath to see if it matches the input. */
! lc = list_head(activeSearchPath);
!
! /* If path->addTemp, first item should be my temp namespace. */
! if (path->addTemp)
! {
! if (lc && lfirst_oid(lc) == myTempNamespace)
! lc = lnext(lc);
! else
! return false;
! }
! /* If path->addCatalog, next item should be pg_catalog. */
! if (path->addCatalog)
! {
! if (lc && lfirst_oid(lc) == PG_CATALOG_NAMESPACE)
! lc = lnext(lc);
! else
! return false;
! }
! /* We should now be looking at the activeCreationNamespace. */
! if (activeCreationNamespace != (lc ? lfirst_oid(lc) : InvalidOid))
! return false;
! /* The remainder of activeSearchPath should match path->schemas. */
! foreach(lcp, path->schemas)
! {
! if (lc && lfirst_oid(lc) == lfirst_oid(lcp))
! lc = lnext(lc);
! else
! return false;
! }
! if (lc)
! return false;
! return true;
}
/*