[feature](query-cache) Support incremental merge for stale query cache entries#65482
Open
asdf2014 wants to merge 1 commit into
Open
[feature](query-cache) Support incremental merge for stale query cache entries#65482asdf2014 wants to merge 1 commit into
asdf2014 wants to merge 1 commit into
Conversation
…e entries Hourly batch loads keep bumping the version of the hot partition, so its query cache entries never hit again and every "last N days" aggregation recomputes the whole partition each hour. This change lets BE reuse a stale entry instead of discarding it: scan only the delta rowsets in (cached_version, current_version], emit their partial aggregation state side by side with the cached partial blocks (the upstream merge aggregation combines both), and write the merged entry back under the new version. Correctness rests on two properties: append-only snapshots decompose as S(v2) = S(v1) + delta, and partial aggregation states merge homomorphically. Every precondition guards one of them, and any violation falls back to a full recompute silently: - FE only sets TQueryCacheParam.allow_incremental (new optional field 8) when the experimental session switch enable_query_cache_incremental is on, the cache point is a non-finalize aggregation directly above the olap scan node, and the selected index is append-only: DUP_KEYS, or merge-on-write UNIQUE_KEYS. - BE re-validates per tablet at decision time: local storage mode, version order, the compaction threshold (query_cache_max_incremental_merge_count, BE config, default 8), keys type, delta capturability, no delete predicates in the delta, and for merge-on-write tables a delete-bitmap window check that rejects any load that rewrote pre-existing keys, so an occasional backfill costs exactly one full recompute and re-bases the entry. A new fragment-level QueryCacheRuntime makes one idempotent decision (HIT / INCREMENTAL / MISS) per instance, pins the entry and pre-captures the delta read source. Centralizing the decision also fixes three pre-existing defects: the scan/cache-source double-lookup race that could write back an empty poisoned entry, row-binlog scans polluting the cache, and build_cache_key failures aborting the whole query instead of degrading to uncached execution. Observability: profile fields HitCacheStale, IncrementalDeltaVersions and IncrementalFallbackReason, plus three BE metrics (query_cache_stale_hit_total, query_cache_incremental_fallback_total, query_cache_write_back_total). Benchmark (80M-row duplicate-key table, 200k-row hourly appends, group by a non-distribution column): a stale query drops from ~307ms (full recompute) to ~19ms with incremental merge, on par with an exact hit, and the cost no longer grows with the base data size.
Contributor
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What problem does this PR solve?
Related PR: N/A
Problem Summary:
For hourly batch-load workloads, every load bumps the tablet version of the
hot partition, so its query cache entries never hit again: each "last N days"
aggregation recomputes the whole hot partition every hour, and BE CPU spikes
during load windows.
This PR adds incremental merge for the query cache (experimental, default
off). When a cache entry's version falls behind, BE reuses it instead of
discarding it: it scans only the delta rowsets in
(cached_version, current_version], emits their partial aggregation stateside by side with the cached partial blocks so the existing upstream merge
aggregation combines both, and writes the merged entry back under the new
version. The execution plan is unchanged.
Measured impact (80M-row duplicate-key table, 200k-row hourly appends,
group by a non-distribution column): a stale query drops from ~307 ms
(full recompute) to ~19 ms with incremental merge, about 16x and on
par with an exact hit (~17 ms); the cost no longer grows with the base data
size (8M rows: 48 ms full vs 19 ms incremental; 80M rows: 307 ms vs 19 ms).
Full numbers in the Verification section below.
Design highlights:
S(v2) = S(v1) ⊎ Δfor append-only data plus thehomomorphism
partial(A ⊎ B) ≡ merge(partial(A), partial(B)). Everyprecondition guards one of the two properties; any violation falls back
to a full recompute silently, so results are always correct.
(
TQueryCacheParam.allow_incremental) only for non-finalize aggregationsdirectly above the olap scan on an append-only index: DUP_KEYS, or
merge-on-write UNIQUE_KEYS. Merge-on-read UNIQUE and AGG tables always
fall back.
in the profile): cloud mode, version order, the compaction threshold
(
query_cache_max_incremental_merge_count, default 8, 0 disables), keystype, delta capturability on the version graph, delete predicates in the
delta, and for merge-on-write tables a delete-bitmap window check that
rejects loads rewriting pre-existing keys. A rare backfill therefore costs
exactly one full recompute, which re-bases the entry, and the next
pure-append load is incremental again.
QueryCacheRuntimemakes one idempotent decision perinstance (HIT / INCREMENTAL / MISS), pins the entry and pre-captures the
delta read source. This also fixes three pre-existing defects: the
scan/cache-source double-lookup race (could write back an empty poisoned
entry), row-binlog scans polluting the cache, and
build_cache_keyfailures aborting the query instead of degrading to uncached execution.
after
query_cache_max_incremental_merge_countmerges the next queryrecomputes in full and compacts the entry; oversized entries keep the
delta-scan benefit but skip the write back.
Verification:
FE UT:
QueryCacheNormalizerTest13/13 (8 assertions on the incrementalauthorization matrix: switch, plan shapes, DUP / MoW / MoR / AGG / nested
aggregation).
BE UT: 34/34 across the decision layer, the incremental scenarios (MoW
pure-append / history-rewrite / irrelevant bitmap entries, version gap,
capture error via debug point, delete predicates) and the operator layer.
llvm-cov: zero uncovered changed lines;
query_cache.cppat 100% linecoverage.
Regression:
query_cache_incrementalpasses on a real 1FE+1BE cluster;every step is checked against a cache-off baseline. BE metrics confirm the
incremental path actually fires (
stale_hit_total+40 across the suite,fallbacks exactly at the three designed spots).
Benchmark (80M-row DUP table, 200k-row hourly appends, group by a
non-distribution column, 5 rounds each):
A stale query becomes as cheap as an exact hit, and its cost no longer
grows with the base data size (8M rows: 48ms full vs 19ms incremental;
80M rows: 307ms vs 19ms).
Release note
Add experimental incremental merge for the query cache: a stale entry can be
reused by scanning only the delta rowsets and merging them with the cached
partial aggregation state. Controlled by the session variable
enable_query_cache_incremental(default off) and the BE configquery_cache_max_incremental_merge_count(default 8).Check List (For Author)
Test
Behavior changed:
Does this need documentation?
Check List (For Reviewer who merge this PR)