mirror of
https://github.com/postgres/postgres.git
synced 2025-05-30 00:02:11 -04:00
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's management overhead exceeds the cost of evaluating the expression. This patch substantially improves that situation, providing roughly 2X speedup for such trivial expressions. First, add infrastructure in the plancache to allow fast re-validation of cached plans that contain no table access, and hence need no locks. Teach plpgsql to use this infrastructure for expressions that it's already deemed "simple" (which in particular will never contain table references). The fast path still requires checking that search_path hasn't changed, so provide a fast path for OverrideSearchPathMatchesCurrent by counting changes that have occurred to the active search path in the current session. This is simplistic but seems enough for now, seeing that PushOverrideSearchPath is not used in any performance-critical cases. Second, manage the refcounts on simple expressions' cached plans using a transaction-lifespan resource owner, so that we only need to take and release an expression's refcount once per transaction not once per expression evaluation. The management of this resource owner exactly parallels the existing management of plpgsql's simple-expression EState. Add some regression tests covering this area, in particular verifying that expression caching doesn't break semantics for search_path changes. Patch by me, but it owes something to previous work by Amit Langote, who recognized that getting rid of plancache-related overhead would be a useful thing to do here. Also thanks to Andres Freund for review. Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
87 lines
2.8 KiB
C
87 lines
2.8 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* resowner.h
|
|
* POSTGRES resource owner definitions.
|
|
*
|
|
* Query-lifespan resources are tracked by associating them with
|
|
* ResourceOwner objects. This provides a simple mechanism for ensuring
|
|
* that such resources are freed at the right time.
|
|
* See utils/resowner/README for more info.
|
|
*
|
|
*
|
|
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/utils/resowner.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef RESOWNER_H
|
|
#define RESOWNER_H
|
|
|
|
|
|
/*
|
|
* ResourceOwner objects are an opaque data structure known only within
|
|
* resowner.c.
|
|
*/
|
|
typedef struct ResourceOwnerData *ResourceOwner;
|
|
|
|
|
|
/*
|
|
* Globally known ResourceOwners
|
|
*/
|
|
extern PGDLLIMPORT ResourceOwner CurrentResourceOwner;
|
|
extern PGDLLIMPORT ResourceOwner CurTransactionResourceOwner;
|
|
extern PGDLLIMPORT ResourceOwner TopTransactionResourceOwner;
|
|
extern PGDLLIMPORT ResourceOwner AuxProcessResourceOwner;
|
|
|
|
/*
|
|
* Resource releasing is done in three phases: pre-locks, locks, and
|
|
* post-locks. The pre-lock phase must release any resources that are
|
|
* visible to other backends (such as pinned buffers); this ensures that
|
|
* when we release a lock that another backend may be waiting on, it will
|
|
* see us as being fully out of our transaction. The post-lock phase
|
|
* should be used for backend-internal cleanup.
|
|
*/
|
|
typedef enum
|
|
{
|
|
RESOURCE_RELEASE_BEFORE_LOCKS,
|
|
RESOURCE_RELEASE_LOCKS,
|
|
RESOURCE_RELEASE_AFTER_LOCKS
|
|
} ResourceReleasePhase;
|
|
|
|
/*
|
|
* Dynamically loaded modules can get control during ResourceOwnerRelease
|
|
* by providing a callback of this form.
|
|
*/
|
|
typedef void (*ResourceReleaseCallback) (ResourceReleasePhase phase,
|
|
bool isCommit,
|
|
bool isTopLevel,
|
|
void *arg);
|
|
|
|
|
|
/*
|
|
* Functions in resowner.c
|
|
*/
|
|
|
|
/* generic routines */
|
|
extern ResourceOwner ResourceOwnerCreate(ResourceOwner parent,
|
|
const char *name);
|
|
extern void ResourceOwnerRelease(ResourceOwner owner,
|
|
ResourceReleasePhase phase,
|
|
bool isCommit,
|
|
bool isTopLevel);
|
|
extern void ResourceOwnerReleaseAllPlanCacheRefs(ResourceOwner owner);
|
|
extern void ResourceOwnerDelete(ResourceOwner owner);
|
|
extern ResourceOwner ResourceOwnerGetParent(ResourceOwner owner);
|
|
extern void ResourceOwnerNewParent(ResourceOwner owner,
|
|
ResourceOwner newparent);
|
|
extern void RegisterResourceReleaseCallback(ResourceReleaseCallback callback,
|
|
void *arg);
|
|
extern void UnregisterResourceReleaseCallback(ResourceReleaseCallback callback,
|
|
void *arg);
|
|
extern void CreateAuxProcessResourceOwner(void);
|
|
extern void ReleaseAuxProcessResources(bool isCommit);
|
|
|
|
#endif /* RESOWNER_H */
|