Global Cache moves PostgreSQL's per-process metadata caches into shared memory, so all processes read from the same cache entries instead of maintaining private copies. This reduces total memory consumption and lowers the risk of out-of-memory (OOM) errors in clusters with many connections or a large number of database objects.
Prerequisites
This feature requires PolarDB for PostgreSQL running PostgreSQL 14 with minor engine version 2.0.14.8.11.0 or later.
Check your current version in the console or by running:
SHOW polardb_version;
If the version does not meet the requirement, upgrade the minor engine version. For instructions, see Version management.
How Global Cache works
PostgreSQL allocates separate metadata caches for each backend process:
-
RelCache (Relation Descriptor Cache): caches relation descriptors, including metadata for tables, views, indexes, and TOAST tables. RelCache is accessed at every stage of SQL processing — reading column definitions, index structures, and partitioned table layouts. A cache miss triggers a scan of the system catalogs to load the data into memory. In native PostgreSQL, RelCache has no eviction mechanism: after the first access, entries are retained until the process exits. If a DDL operation modifies a table's metadata, it broadcasts a cache invalidation message, and RelCache removes the invalidated entry from memory.
-
CatCache/SysCache (System Catalog Cache): caches tuples from system catalogs. SysCache, built on top of CatCache, exposes a key-value (KV) interface for fast lookups, such as resolving a name from an object identifier (OID) or finding the parameter count of a function. A cache miss loads the data from the system catalogs. The loading and invalidation processes for CatCache are almost identical to those for RelCache.
Because RelCache and CatCache are private to each process, memory consumption grows with the number of connections and database objects. Each new connection allocates its own copy of every cache entry it touches. Under heavy connection counts or schemas with many tables, views, and indexes, this per-process overhead can exhaust available memory and trigger OOM errors.
Global Cache addresses this by placing both caches in shared memory, where all processes read and write the same entries. Global Cache includes:
-
Global RelCache: a shared relation descriptor cache, replacing per-process RelCache
-
Global CatCache: a shared system catalog cache, replacing per-process CatCache/SysCache
Configure Global Cache
Global Cache is enabled by default. The following parameters control its behavior.
Enable or disable Global Cache
| Parameter | Level | Default | Description |
|---|---|---|---|
polar_enable_global_catcache |
PGC_USERSET | on |
Enables or disables Global CatCache. Set to off to disable. |
polar_enable_global_relcache |
PGC_USERSET | on |
Enables or disables Global RelCache. Set to off to disable. |
Size Global Cache
| Parameter | Level | Default | Range | Description |
|---|---|---|---|---|
polar_sgc_max_size |
PGC_POSTMASTER | 72 MB | 0 to INT_MAX | Total memory allocated to Global Cache. Changing this parameter requires a restart. |
polar_global_catcache_size |
PGC_SIGHUP | 32 MB | 0 to polar_sgc_max_size |
Memory allocated to Global CatCache. |
polar_global_relcache_size |
PGC_SIGHUP | 32 MB | 0 to polar_sgc_max_size |
Memory allocated to Global RelCache. |
Sizing notes:
-
Set
polar_sgc_max_sizeto a value greater than the sum ofpolar_global_catcache_sizeandpolar_global_relcache_size. A portion of the allocated memory is reserved for internal management structures such as hash tables. -
polar_global_catcache_sizeandpolar_global_relcache_sizecan be adjusted online without a restart, as long as the new values do not exceedpolar_sgc_max_size. -
Keep cache capacity sufficient. When the cache is full and eviction is triggered, evicted entries must be reloaded from disk on next access, causing extra I/O and performance degradation.
-
Scale down a live cache with caution. Reducing cache size while the database is running forces eviction of existing entries. Perform this operation during low-traffic periods.
Monitor Global Cache
All monitoring views are provided by the polar_global_cache extension. Install it once per database:
CREATE EXTENSION polar_global_cache;
Diagnose capacity issues
The most important signal is whether eviction is occurring. When nevict, nevict_active, or nevict_fail are non-zero, the cache is undersized: entries are being evicted under the Least Recently Used (LRU) policy, and subsequent accesses to those entries require loading data from disk, increasing I/O and degrading query performance.
To check whether eviction is occurring:
SELECT cache_name, nevict, nevict_active, nevict_fail
FROM polar_global_cache_stat;
If any eviction metrics are non-zero, increase cache size by adjusting polar_global_catcache_size or polar_global_relcache_size.
To evaluate cache hit rate, use nlookup and nlookup_miss from the same view:
SELECT cache_name,
nlookup,
nlookup_miss,
round((1 - nlookup_miss::numeric / nullif(nlookup, 0)) * 100, 2) AS hit_rate_pct
FROM polar_global_cache_stat;
Hit rate may be low immediately after startup while the cache is warming up. Once the workload reaches steady state, a low hit rate combined with non-zero eviction metrics indicates the cache is undersized.
Global Cache statistics
Query polar_global_cache_stat to see aggregate statistics for Global RelCache and Global CatCache:
SELECT * FROM polar_global_cache_stat;
Example output:
-[ RECORD 1 ]----+----------------
cache_name | Global CatCache
elems | 2805
nlookup | 74233
nlookup_miss | 43576
ninsert | 9478
nmove | 0
ndelete | 0
ninvalidate | 35843
nflush | 1
nevict | 0
nevict_active | 0
nevict_fail | 0
lru_active_len | 402
lru_inactive_len | 2403
data_allocator | 2
meta_allocator | 1
component_id | 1
-[ RECORD 2 ]----+----------------
cache_name | Global RelCache
elems | 95
nlookup | 1203
nlookup_miss | 1005
ninsert | 265
nmove | 0
ndelete | 0
ninvalidate | 4404
nflush | 1
nevict | 0
nevict_active | 0
nevict_fail | 0
lru_active_len | 3
lru_inactive_len | 92
data_allocator | 3
meta_allocator | 1
component_id | 2
Metric descriptions:
| Metric | Description |
|---|---|
elems |
Current number of entries in the cache. |
nlookup |
Total number of cache lookups. |
nlookup_miss |
Total number of lookups that missed the cache. Use this with nlookup to calculate the hit rate. |
ninsert |
Number of entries inserted into the cache. |
nmove, ndelete |
Number of entries moved or deleted during online cache scaling. |
ninvalidate |
Number of cache entries invalidated, for example by Data Definition Language (DDL) operations. |
nflush |
Number of times the entire cache was flushed, triggered by a special invalidation message or a command such as DROP DATABASE. |
nevict |
Total number of entries evicted under the LRU policy. Non-zero values indicate the cache is undersized. |
nevict_active |
Number of entries evicted from the active LRU list. |
nevict_fail |
Number of failed eviction attempts, due to the entry being in use or a concurrency conflict. These can be ignored. |
lru_active_len |
Number of entries in the active LRU list. |
lru_inactive_len |
Number of entries in the inactive LRU list. Inactive entries are evicted first. |
Local cache statistics (per-process view)
polar_cache_stat reports statistics for per-process private caches (RelCache and CatCache). Although the view shows private cache data, the results aggregate across all processes.
SELECT * FROM polar_cache_stat;
Example output:
-[ RECORD 1 ]-+--------------
cache_name | Proc CatCache
nlookup | 779844
nlookup_miss | 82390
ninsert | 150876
ndelete | 139690
ninvalidate | 74231
nevict | 126474
nevict_active | 1808
evict_fail | 0
-[ RECORD 2 ]-+--------------
cache_name | Proc RelCache
nlookup | 295183
nlookup_miss | 4632
ninsert | 25968
ndelete | 3277
ninvalidate | 8856
nevict | 0
nevict_active | 0
evict_fail | 0
The metrics are a subset of those in polar_global_cache_stat. See the metric descriptions above.
Global CatCache statistics
polar_global_catcache_stat provides per-cache-index statistics for Global CatCache, with additional _clist fields for CatList objects. CatCache holds two object types: CatTuple and CatList. The _clist metrics track CatList-specific operations and can typically be ignored.
SELECT * FROM polar_global_catcache_stat;
Example output:
-[ RECORD 1 ]-------+----
elems | 34
nlookup | 853
nlookup_miss | 852
ninsert | 34
nmove | 0
ndelete | 0
ninvalidate | 0
nflush | 0
nevict | 0
nevict_active | 0
nevict_fail | 0
nlookup_clist | 41
nlookup_miss_clist | 41
ninsert_clist | 0
nmove_clist | 0
ndelete_clist | 0
ninvalidate_clist | 0
nevict_clist | 0
neivct_active_clist | 0
rehash_fail | 0
meta_alloc_fail | 0
data_alloc_fail | 0
lru_active_len | 0
lru_inactive_len | 34
component_id | 1
Local CatCache statistics
polar_catcache_stat shows private CatCache statistics for the current session. The metrics are a subset of those in polar_global_catcache_stat with the same meanings.
SELECT * FROM polar_catcache_stat;
Example output:
-[ RECORD 1 ]------+-----
nlookup | 2060
nlookup_miss | 898
ninsert | 883
ndelete | 753
ninvalidate | 0
nevict | 753
nevict_active | 2
evict_fail | 0
nlookup_clist | 41
nlookup_miss_clist | 41
ninsert_clist | 41
ndelete_clist | 41
Global RelCache statistics
polar_global_relcache_stat shows statistics for Global RelCache.
SELECT * FROM polar_global_relcache_stat;
Example output:
-[ RECORD 1 ]----+-----
elems | 61
nlookup | 930
nlookup_miss | 836
ninsert | 221
nmove | 0
ndelete | 0
ninvalidate | 4344
nflush | 1
nevict | 0
nevict_active | 0
nevict_fail | 0
meta_alloc_fail | 0
data_alloc_fail | 0
lru_active_len | 3
lru_inactive_len | 58
component_id | 2
Local RelCache statistics (current session)
polar_relcache_stat shows RelCache statistics for the current session only.
SELECT * FROM polar_relcache_stat;
Example output:
-[ RECORD 1 ]-+-------
nlookup | 293458
nlookup_miss | 4535
ninsert | 20239
ndelete | 3277
ninvalidate | 8856
nevict | 0
nevict_active | 0
evict_fail | 0