Expand description
v6.2.6 — Memoize cache for correlated subqueries.
When a WHERE clause references a scalar subquery whose inner
body depends on the outer row’s column values (the classic
WHERE id IN (SELECT MAX(x) FROM y WHERE y.k = outer.k)
shape), the engine’s current behaviour re-runs the inner
SELECT once per outer row — O(outer_rows × inner_cost) work
even when many outer rows share the same correlated key.
v6.2.6 wraps that path with a per-query MemoizeCache:
before running the inner, hash the (subquery identity, outer-
row values) key and look it up; cache hits return the prior
result without re-executing. Caps:
- 1024 entries (configurable via the planner’s
[
Self::with_max_entries]) - 16 MiB of cumulative cached
Valuebytes (v5.5 per-query memory budget’s 1/16 share; configurable via [Self::with_max_bytes])
When either cap is hit, the least-recently-used entry is evicted before insertion.
v6.2.6 ships the simple linear-vec LRU. v6.2.x can swap to a
BTreeMap + LinkedList for sub-O(n) lookup if it ever
matters; the gate is “≥ 5× speedup on the repeated-key
workload” which the linear scan clears at scale-1k.
Modules§
- counters
- v7.37.7 (mailrs cascade contention round 2 instrumentation) —
runtime counters to disambiguate samply attribution.
samplyreported 67.8% CPU inMemoizeCache::new+ drop_in_place under 20-worker stress, but K01 (eager-alloc → lazy) didn’t move cascade amplification — suggesting either the attribution was off or the eager 96 KB alloc isn’t the dominant cost. These counters provide ground truth: how many times isnew()actually called, how many entries does any cache ever hold, how many caches die empty. Read once at end of bench viaMemoizeCache::counter_snapshot().
Structs§
- Cache
Key - Cache key — the subquery’s textual identity plus the outer row’s value tuple. Two scalar-subquery node positions with identical Display text are treated as the same subquery for caching purposes (sound: equal Display → equal AST).
- InList
SetEntry - Memoize
Cache
Enums§
- InList
Set - v7.30.2 (mailrs round-25) - canonicalised membership set for a
large all-literal
INlist. Integer literals canonicalise to i64 (cross-widthInt = BigIntstays correct); string literals stay verbatim. Mixed or exotic families are not eligible and keep the linearapply_binaryscan.
Constants§
- DEFAULT_
MAX_ BYTES - v6.2.6 — default cumulative bytes cap. 16 MiB matches the v5.5 per-query budget’s 1/16 share.
- DEFAULT_
MAX_ ENTRIES - v6.2.6 — default cache size cap. Matches the design’s “1024 entries” figure (V6_2_DESIGN.md L2 row 6).
Type Aliases§
- Exists
Set - v7.34 (mailrs conn-pool-exhaustion P0) - decorrelated
[NOT] EXISTSsemi/anti-join: the outer correlation columns (in key order) and the set of encoded inner key-tuples that have >=1 matching inner row, built in ONE scan. An outer row’s EXISTS reduces to a membership test, turning O(outer x inner-exec) per-row work into O(scan + outer lookups) - PG’s Hash Semi/Anti Join. v7.39 (round 596) — the outer side is an EXPRESSION, not just a column.EXISTS (SELECT 1 FROM b WHERE b.id = a.id + 1)correlates just as exactly asb.id = a.iddoes, but only the column shape decorrelated, so the expression shape ran the subquery once per outer row: O(n²), and measured at 427 ms / 1.6 s / 6.4 s / >25 s as the table went 2k / 4k / 8k / 16k, where the column shape stays linear (0.5 / 0.9 / 1.5 / 3.2 ms). - Expr
Plan - v7.29 (3c) - per-expression resolution plan: for the i-th scalar subquery node (pre-order) of a host expression, the shared batch map (None = unbatchable, resolve per row). Keyed by the HOST expression’s address - callers guarantee the expression outlives the per-query memo (aggregate items / WHERE trees do). The stored subquery count guards against address reuse. (subquery count, per-subquery batch maps, hollow template). The template is the host expression with every scalar subquery BODY emptied - cloning it per row costs nodes, not whole subquery ASTs (the splice walk replaces the hollow nodes by pre-order).
- Group
Map - v7.29 - one batch-evaluated correlated subquery: the outer key column and the key -> value map.