Partial Result Cache (PTRC) caches intermediate result sets produced by specific operators in a query and reuses them on subsequent executions of the same operator. It performs best when the correlated parameter of an operator has many duplicate values in the driving table — the more duplicates, the higher the cache hit rate, and the greater the performance gain.
How it works
PTRC is "partial" in two ways:
-
It caches intermediate result sets of specific operators, not the entire query result.
-
Even for eligible operators, it does not cache all result sets — the cache scope is bounded by memory limits.
| Aspect | Traditional query cache | PTRC |
|---|---|---|
| Granularity | Entire query result | Operator-level intermediate result |
| Lifecycle | Persists across queries | Single query only |
| Node consistency | Can cause inconsistency across nodes | No inconsistency risk |
| Applicable scope | Narrow | Broader |
PTRC stores results in key-value pairs, where the key is the correlated parameter of the operator and the value is the cached intermediate result. Each time the operator runs, the system checks whether the key exists in the cache:
-
Cache miss: the operator runs and the result is added to the cache.
-
Cache hit: the cached result is returned directly, skipping execution.
Eligible operators
An operator is eligible for PTRC if both conditions are met:
-
It depends on a correlated parameter and runs multiple times within a single query. Correlated subqueries and nested loop joins are typical examples.
-
Its correlated parameter does not change between executions — operators that contain non-deterministic functions such as
RAND(),NOW(), or user-defined functions (UDFs) are not eligible.
A correlated parameter is a value from the outer query that the operator depends on.
Example: TPC-H Q17
TPC-H Q17 illustrates how PTRC works in practice.
select
sum(l_extendedprice) / 7.0 as avg_yearly
from
lineitem,
part
where
p_partkey = l_partkey
and p_brand = 'Brand#34'
and p_container = 'MED BOX'
and l_quantity < (
select
0.2 * avg(l_quantity)
from
lineitem
where
l_partkey = p_partkey
);
The correlated subquery runs once for each row produced by the join of part and lineitem. The correlated parameter is p_partkey — the driving table column used in the join condition. Because the join result contains many rows with the same p_partkey value, PTRC caches the subquery result for each distinct p_partkey and reuses it for subsequent rows with the same value. The key is p_partkey; the value is true or false.
To confirm that PTRC is active, run EXPLAIN on the query. An operator named Partial result cache appears before the subquery in the execution plan.
Prerequisites
Before enabling or tuning PTRC, confirm that your cluster meets the following requirements:
-
A PolarDB for MySQL cluster running MySQL 8.0
-
Revision version 8.0.2.2.9 or later
To check your cluster version, see Engine versions.
Parameters
PTRC is enabled by default and controlled through six parameters. Together, they define three aspects of PTRC behavior: whether to engage, when to engage, and what to do when memory fills up.
| Parameter | Level | Default | Valid values | Description |
|---|---|---|---|---|
partial_result_cache_enabled |
Global/Session | ON | ON, OFF | Enables or disables PTRC. |
partial_result_cache_cost_threshold |
Global/Session | 10000 | 0–18446744073709551615 | The query cost threshold. PTRC is considered only if the overall query cost exceeds this value. |
partial_result_cache_check_frequency |
Global/Session | 200 | 0–18446744073709551615 | The number of cache misses between hit rate recalculations by the dynamic feedback mechanism. |
partial_result_cache_low_hit_rate |
Global/Session | 20 | 0–100 | The lower hit rate threshold (percentage). PTRC is not used if the estimated hit rate is below this value, and is disabled mid-query if the actual hit rate falls below it. Must be lower than partial_result_cache_high_hit_rate. |
partial_result_cache_high_hit_rate |
Global/Session | 70 | 0–100 | The upper hit rate threshold (percentage). When the memory limit is reached, cached results are dumped to disk if the hit rate exceeds this value. Must be higher than partial_result_cache_low_hit_rate. |
partial_result_cache_max_mem_size |
Global/Session | 67108864 | 0–18446744073709551615 | The maximum memory PTRC can use for a single query, in bytes. Default is 64 MiB. |
How the optimizer decides whether to use PTRC
PTRC consumes resources — it performs a cache lookup on every operator execution and holds cached results in memory. The query optimizer uses partial_result_cache_cost_threshold and partial_result_cache_low_hit_rate to decide whether the benefit justifies the cost.
Step 1: Cost check
If the overall query cost is below partial_result_cache_cost_threshold, the optimizer skips PTRC entirely. For short queries, the cache lookup overhead can outweigh any performance gain.
Step 2: Hit rate estimation
If the query cost exceeds the threshold, the optimizer identifies all eligible operators and estimates the hit rate for each:
hit_rate = (fanout - ndv) / fanout
-
fanout: the total number of times the operator executes. -
ndv: the number of distinct values of the correlated parameter (the cache key).
If the estimated hit rate is below partial_result_cache_low_hit_rate, PTRC is not used for that operator.
When estimation is unavailable
The optimizer relies on indexes or histograms to estimate ndv. If the correlated parameter column has neither, ndv cannot be accurately estimated. In that case, the optimizer enables PTRC without a hit rate estimate and delegates the decision to the dynamic feedback mechanism at runtime.
Dynamic feedback mechanism
At runtime, PTRC monitors its own hit rate and memory usage and adjusts behavior accordingly.
Hit rate is recalculated every partial_result_cache_check_frequency cache misses (default: every 200 misses). It is also recalculated when memory usage reaches partial_result_cache_max_mem_size.
Based on the current hit rate, one of three actions is taken:
| Condition | Action |
|---|---|
Hit rate < partial_result_cache_low_hit_rate |
Disable PTRC for the remainder of the query. |
Hit rate > partial_result_cache_high_hit_rate |
Dump the in-memory cache to disk. New cache entries are also written to disk. Performance degradation is minimal because the hit rate is high. |
| Hit rate between the two thresholds | Apply LRU (Least Recently Used) eviction: remove the least-used entries and cache new data. If memory fills up again, the feedback mechanism is triggered again. |
When the memory limit is reached, the feedback mechanism is triggered for all operators that have PTRC enabled in the query.
Performance considerations
Two factors determine how much PTRC improves performance:
-
Operator cost: the higher the cost of the cached operator, the larger the gain. For cheap operators, the improvement is minimal.
-
Cache hit rate: the higher the hit rate, the larger the gain.
In TPC-H Q17, the cache hit rate is 96%. The following figures show the query and its execution plan with PTRC enabled, along with the performance improvement.


PTRC is designed for queries with complex operators that depend on correlated parameters. Operators for which PTRC is suitable include correlated subqueries and nested loop joins (inner joins, outer joins, semi joins, and anti joins).