Skip to content

[feature](query-cache) Extend stale-entry incremental merge to cloud mode#65788

Open
asdf2014 wants to merge 2 commits into
apache:masterfrom
asdf2014:query-cache-incremental-cloud
Open

[feature](query-cache) Extend stale-entry incremental merge to cloud mode#65788
asdf2014 wants to merge 2 commits into
apache:masterfrom
asdf2014:query-cache-incremental-cloud

Conversation

@asdf2014

Copy link
Copy Markdown
Member

What problem does this PR solve?

Issue Number: close #xxx

Related PR: #65482

Problem Summary:

Extends the stale query cache entry incremental merge (#65482) from the shared-nothing (local storage) deployment to the compute-storage decoupled (cloud) mode.

In cloud mode a tablet's rowsets, and for merge-on-write tables its delete bitmap, are a lazily synced copy of the meta service. The base change refused incremental merge on cloud outright. This brings the same optimization to cloud by syncing each stale tablet's view to the queried version before capturing the delta:

  • Per-tablet meta-service syncs are fanned out in parallel and awaited with a fast-fail budget (query_cache_decision_sync_timeout_ms, new cloud BE config, default 2000 ms, changeable at runtime). The decision runs on the bounded query-admission pool, so on a meta-service brownout it falls back to a full recompute rather than holding that thread. A value <= 0 disables cloud incremental merge as a fail-safe.
  • The presync brings the delete bitmap to the queried version, so the merge-on-write history-rewrite check sees exactly what the read path sees; the later scan-node sync takes the same no-op shortcut, so the RPC count per query does not grow.
  • The cached-side rowsets are pinned during bitmap classification so a concurrent unused-rowset GC cannot retire the evidence (both storage engines drop a retired rowset's bitmap only once nothing else references it).
  • A query reading a version-inexact view (query_freshness_tolerance_ms or enable_prefer_cached_rowset) is excluded from incremental merge and, on cloud, from the cache write-back, so no entry whose content mismatches its version stamp is ever created.

Observability: new counter query_cache_decision_sync_time_ms (only advances in cloud mode) records the wall time the decision spent syncing tablet views before capturing the delta.

Release note

Query Cache incremental merge now works in the compute-storage decoupled (cloud) mode. New BE config query_cache_decision_sync_timeout_ms (default 2000, changeable at runtime) bounds the decision's tablet view sync; on timeout the query falls back to one full recompute.

Check List (For Author)

  • Test

    • Regression test
    • Unit Test
    • Manual test (add detailed scripts or steps below)
      • Ran the query_cache_incremental regression suite and a four-phase benchmark (no cache, exact hit, incremental merge, incremental off) on a real compute-storage decoupled cluster (FoundationDB + meta service + MinIO): the stale-hit and fallback metrics match the shared-nothing baseline, and the decision sync time stays in the tens of milliseconds.
    • No need to test or manual test. Explain why:
      • This is a refactor/code format and no logic has been changed.
      • Previous test can cover this change.
      • No code files have been changed.
      • Other reason
  • Behavior changed:

    • No.
    • Yes. On cloud, a stale cache entry can now be reused through incremental merge instead of always recomputing in full. The profile gains two cloud fallback reasons (cloud rowset sync failed, cloud rowset sync timed out).
  • Does this need documentation?

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

…mode

The base incremental merge (apache#65482) only ran in the shared-nothing (local
storage) deployment. This extends it to the compute-storage decoupled (cloud)
mode.

In cloud mode a tablet's rowset list, and for merge-on-write tables its delete
bitmap, are a lazily synced copy of the meta service. The incremental decision
runs in operator init, before the scan node's own sync round, so it must first
bring each stale tablet's local view up to the queried version and only then
capture the delta.

Decision path:
- _presync_cloud_delta_tablets fans the per-tablet meta-service syncs out in
  parallel (reusing init_scanner_sync_rowsets_parallelism) and waits on them
  with a fast-fail budget instead of blocking. The decision runs on the bounded
  query-admission pool (light_work_pool), so a meta-service brownout that
  stalled these RPCs for the full retry budget could exhaust the pool and reject
  query admission cluster-wide. If the fan-out does not finish within
  query_cache_decision_sync_timeout_ms (new cloud BE config, default 2000,
  changeable at runtime) the decision abandons the wait and falls the whole
  instance back to a full recompute. A value <= 0 disables cloud incremental
  merge as a fail-safe.
- The sync brings the delete bitmap up to the queried version
  (sync_delete_bitmap=true), so the history-rewrite classification reads exactly
  what the merge-on-write read path sees. The later scan-node sync takes the
  same no-op shortcut (its local view is already at the queried version),
  so it issues no extra meta-service RPC and the RPC count per query does not
  grow.
- While the classification reads the cached-side delete bitmap, the cached
  rowsets are pinned so a concurrent unused-rowset GC cannot retire the
  evidence. Both engines drop a retired rowset's bitmap only once nothing else
  references it, so raising the use count blocks the drop in either deployment
  mode.

Correctness guard: a query that reads a version-inexact view
(query_freshness_tolerance_ms or enable_prefer_cached_rowset) does not use
incremental merge, since the delta capture always targets the exact queried
version. The exclusion is a deliberately mode-agnostic gate. On cloud such a
query also skips the query cache write-back, so no entry whose content
mismatches its version stamp is ever created.

Observability: new counter query_cache_decision_sync_time_ms records the wall
time the decision spent syncing tablet views before capturing the delta. It
only advances in cloud mode.

Tests: BE unit tests cover the cloud decision paths (sync-then-capture, the
timeout fallback, the merge-on-write bitmap rewrite check, the non-cloud-tablet
and load-failure fallbacks, the no-op shortcut, and the write-back
suppression). The FE QueryCacheNormalizerTest covers the freshness and
prefer-cached gate. The query_cache_incremental regression suite now runs in
cloud mode too, with auto-compaction disabled on its tables so the stale-hit
metric assertions stay deterministic.
@asdf2014
asdf2014 requested a review from gavinchou as a code owner July 19, 2026 06:47
@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@asdf2014

Copy link
Copy Markdown
Member Author

run buildall

@asdf2014

Copy link
Copy Markdown
Member Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes. The PR's goal—reuse stale query-cache entries through cloud incremental merge—is valuable, but the current implementation can classify MOW history against an incomplete delete bitmap, leaves timed-out metadata work without query/engine ownership, and contains mode/upgrade/test regressions.

Critical checkpoint conclusions:

  • Goal and proof: the happy-path tests exercise cloud incremental decisions, but they do not prove the rowset-current/bitmap-incomplete state or cancellation/shutdown invariants, so the goal is not safely accomplished.
  • Scope and focus: the 14-file change is generally focused on cache decisions, cloud sync, metrics, and tests; the blockers are within that intended scope.
  • Concurrency and locks: per-tablet _sync_meta_lock ordering remains consistent and candidate construction stays outside the fragment-wide lock, but each query can launch an unbounded detached fanout. New driver/worker bthreads have no query/background thread context or cancellation owner.
  • Lifecycle/static initialization: there is no new cross-TU static-initialization dependency. The non-intuitive future/bthread lifecycle is unsafe because timeout destroys only the future while callbacks retain CloudTablet objects referencing an engine that shutdown does not join them before destroying.
  • Configuration: the new mutable timeout is read dynamically, but a non-positive value still launches work before immediately abandoning it; it must not create ownerless work.
  • Compatibility: no storage format or symbol serialization changes are introduced, but rolling old-FE/new-BE requests can bypass freshness/prefer behavior because the upgraded BE removed the cloud fallback without its own compatibility gate.
  • Parallel paths: local scans ignore both cloud knobs, and cloud MOW ignores prefer-cached-rowset, yet raw values disable incremental/write-back on those exact paths. Full-compaction tablet materialization is also a parallel sync path that can omit the bitmap.
  • Conditional invariants: endpoint/version checks are well explained, but _max_version >= query_version is not proof of delete-bitmap completeness; the comments acknowledge this limitation without making the MOW decision conservative.
  • Error handling: sync statuses are checked and failure reasons/logs carry useful tablet context. The timeout path's defect is ownership/cancellation, not a silently ignored Status.
  • Memory safety/accounting: shared result storage avoids a frame-use-after-free, but callbacks can outlive CloudStorageEngine, and their metadata/delete-bitmap allocations lack the required bthread memory-tracker attachment.
  • Data correctness: visible delta endpoints are checked, but missing old bitmap markers can make a rewrite appear append-only and publish an incorrect version-stamped cache entry.
  • Tests and results: BE/FE unit coverage and a regression were added, but the two critical negative lifecycle/bitmap cases are absent and the cloud metric oracle is routing-dependent. CheckStyle and the reported Cloud UT status pass; both Clang Formatter checks fail and a local clang-format-16 dry run reproduces changed-file violations. macOS BE UT fails before compilation because its runner exposes JDK 25 instead of required JDK 17; TeamCity compile/BE UT/FE UT/performance checks are still pending. Per the review-runner contract, no builds or test suites were launched locally.
  • Observability: the new stale-hit/fallback/sync-time metrics and sampled logs are useful, but aggregating BE-local counters cannot prove that an unpinned query used a stale entry.
  • Transaction, persistence, and writes: no EditLog, transaction, or durable metadata protocol changes are present. Query-cache publication is the relevant write and is unsafe in the incomplete-bitmap sequence; BE crash/shutdown can also intersect detached sync work.
  • FE/BE variables: no new thrift field is added; existing query options are reused. Same-version FE/BE use is aligned, but mixed-version behavior needs a BE-side guard.
  • Performance: per-instance parallelism reduces healthy latency, but no global bound exists across timed-out queries; raw-option gating can also eliminate cache fills/reuse on exact paths.
  • BE null/nullable handling: not applicable; no column-nullability conversion or row-level nullable access is changed.
  • Other issues: two formatter checks are currently red. No additional user focus was supplied beyond the complete PR review.

Comment thread be/src/runtime/query_cache/query_cache.cpp
Comment thread be/src/runtime/query_cache/query_cache.cpp Outdated
Comment thread be/src/runtime/query_cache/query_cache.cpp
Comment thread regression-test/suites/query_p0/cache/query_cache_incremental.groovy Outdated
@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 29965 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 860115c67698d3a81716cea34980303ad8a726cc, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17640	4247	4226	4226
q2	2027	327	203	203
q3	10300	1479	860	860
q4	4683	470	340	340
q5	7574	849	583	583
q6	192	177	144	144
q7	779	837	609	609
q8	9324	1693	1684	1684
q9	5742	4334	4370	4334
q10	6807	1771	1492	1492
q11	511	356	325	325
q12	759	576	471	471
q13	18114	3408	2730	2730
q14	269	266	238	238
q15	q16	801	789	723	723
q17	1019	1033	1067	1033
q18	6970	5901	5587	5587
q19	1179	1287	1047	1047
q20	792	680	575	575
q21	5523	2715	2456	2456
q22	436	363	305	305
Total cold run time: 101441 ms
Total hot run time: 29965 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4413	4480	4533	4480
q2	320	337	230	230
q3	4691	5052	4449	4449
q4	2093	2190	1387	1387
q5	4515	4350	4362	4350
q6	236	178	136	136
q7	2093	2092	1692	1692
q8	2706	2342	2351	2342
q9	8090	8132	8201	8132
q10	4683	4673	4218	4218
q11	608	458	416	416
q12	783	795	542	542
q13	3288	3726	2916	2916
q14	298	308	280	280
q15	q16	755	739	653	653
q17	1456	1413	1541	1413
q18	8165	7555	7472	7472
q19	1219	1075	1090	1075
q20	2214	2213	1947	1947
q21	5311	4684	4495	4495
q22	545	506	403	403
Total cold run time: 58482 ms
Total hot run time: 53028 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 178153 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 860115c67698d3a81716cea34980303ad8a726cc, data reload: false

query5	4317	634	473	473
query6	470	227	202	202
query7	4862	619	340	340
query8	353	197	170	170
query9	8760	4101	4090	4090
query10	484	371	308	308
query11	5927	2333	2115	2115
query12	160	106	106	106
query13	1267	596	457	457
query14	6255	5201	4882	4882
query14_1	4247	4273	4239	4239
query15	214	207	192	192
query16	1074	485	488	485
query17	1190	688	557	557
query18	2454	460	340	340
query19	205	181	142	142
query20	113	107	108	107
query21	240	166	134	134
query22	13545	13530	13321	13321
query23	17302	16521	16110	16110
query23_1	16221	16238	16274	16238
query24	7548	1758	1297	1297
query24_1	1311	1287	1290	1287
query25	526	444	361	361
query26	1328	341	227	227
query27	2599	647	381	381
query28	4453	2016	1967	1967
query29	1082	601	483	483
query30	351	274	230	230
query31	1107	1085	964	964
query32	110	63	62	62
query33	509	322	255	255
query34	1163	1146	648	648
query35	770	799	668	668
query36	1222	1167	1088	1088
query37	150	103	95	95
query38	1877	1698	1636	1636
query39	891	875	889	875
query39_1	828	852	855	852
query40	258	171	141	141
query41	64	63	64	63
query42	96	91	92	91
query43	325	318	287	287
query44	1426	778	767	767
query45	193	180	174	174
query46	1079	1192	727	727
query47	2097	2078	1935	1935
query48	419	414	292	292
query49	586	444	314	314
query50	1076	458	353	353
query51	10304	10750	10688	10688
query52	88	88	74	74
query53	265	283	202	202
query54	284	247	214	214
query55	78	72	65	65
query56	284	299	274	274
query57	1320	1302	1213	1213
query58	283	263	258	258
query59	1572	1662	1439	1439
query60	306	275	255	255
query61	153	151	151	151
query62	540	499	419	419
query63	256	208	199	199
query64	2906	1205	998	998
query65	4730	4664	4650	4650
query66	1844	527	390	390
query67	28664	29322	29127	29127
query68	3061	1476	1033	1033
query69	419	308	286	286
query70	1108	951	968	951
query71	382	351	325	325
query72	3138	2680	2320	2320
query73	804	785	456	456
query74	5100	4934	4760	4760
query75	2539	2515	2142	2142
query76	2326	1192	786	786
query77	347	380	302	302
query78	11869	11893	11173	11173
query79	1271	1205	777	777
query80	611	561	499	499
query81	456	342	297	297
query82	244	165	125	125
query83	318	337	304	304
query84	281	164	128	128
query85	918	621	508	508
query86	343	290	268	268
query87	1811	1821	1749	1749
query88	3704	2792	2794	2792
query89	421	393	334	334
query90	2184	212	208	208
query91	202	198	171	171
query92	69	60	55	55
query93	1560	1557	1069	1069
query94	536	371	311	311
query95	793	604	471	471
query96	1111	802	352	352
query97	2602	2645	2495	2495
query98	216	207	202	202
query99	1098	1125	976	976
Total cold run time: 261084 ms
Total hot run time: 178153 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 25.17 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 860115c67698d3a81716cea34980303ad8a726cc, data reload: false

query1	0.00	0.00	0.00
query2	0.10	0.05	0.08
query3	0.26	0.14	0.13
query4	1.61	0.14	0.15
query5	0.24	0.23	0.23
query6	1.28	1.05	1.05
query7	0.04	0.00	0.00
query8	0.06	0.03	0.04
query9	0.38	0.32	0.32
query10	0.54	0.55	0.56
query11	0.20	0.14	0.14
query12	0.18	0.15	0.15
query13	0.47	0.47	0.48
query14	1.02	1.01	1.01
query15	0.62	0.61	0.58
query16	0.32	0.33	0.33
query17	1.12	1.06	1.10
query18	0.25	0.22	0.23
query19	2.02	2.01	1.94
query20	0.01	0.02	0.01
query21	15.43	0.21	0.14
query22	4.77	0.05	0.05
query23	16.11	0.30	0.12
query24	3.05	0.43	0.31
query25	0.12	0.06	0.04
query26	0.75	0.22	0.15
query27	0.04	0.04	0.04
query28	3.53	0.92	0.55
query29	12.46	4.20	3.31
query30	0.28	0.16	0.15
query31	2.77	0.61	0.31
query32	3.22	0.59	0.49
query33	3.29	3.23	3.32
query34	15.48	4.27	3.56
query35	3.52	3.54	3.52
query36	0.54	0.43	0.44
query37	0.09	0.06	0.07
query38	0.05	0.04	0.05
query39	0.04	0.03	0.03
query40	0.19	0.16	0.15
query41	0.08	0.03	0.02
query42	0.04	0.02	0.02
query43	0.04	0.04	0.04
Total cold run time: 96.61 s
Total hot run time: 25.17 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 98.00% (98/100) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 57.46% (23956/41690)
Line Coverage 41.23% (235873/572141)
Region Coverage 37.04% (186352/503120)
Branch Coverage 38.23% (83654/218838)

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 99.00% (99/100) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 73.57% (29920/40668)
Line Coverage 57.35% (326096/568622)
Region Coverage 53.59% (270624/505012)
Branch Coverage 54.70% (119779/218980)

Follow-up on PR apache#65788 addressing the review of the cloud incremental merge
change. No storage format or symbol change; the only wire change is one optional,
appended thrift field.

Ownership and bound of the cloud decision pre-sync:
- The per-tablet decision syncs no longer run on raw detached bthreads. They run
  on a dedicated, bounded, engine-owned ThreadPool (query_cache_delta_sync_pool).
  stop() drains it first, before the compaction and delete-bitmap pools its
  sync_rowsets callbacks depend on and before ~CloudStorageEngine destroys
  _meta_mgr/_tablet_mgr, so a task that outlived a timed-out query always runs
  against a live engine and none can survive it.
- The pool has a fixed width and a bounded queue (config query_cache_delta_sync_
  thread / query_cache_delta_sync_max_pending_tasks, both validated at startup),
  so a meta-service brownout can neither spawn an unbounded fanout nor grow the
  backlog without bound. Its workers are pre-started at engine construction and
  verified present with a CHECK on the worker count (ThreadPool::init swallows
  per-thread start failures, so a successful build alone proves nothing): submit
  is therefore pure enqueue and never creates a thread on the query admission
  path.
- One absolute deadline, anchored at the fan-out start, covers submission plus
  the wait, so nothing can re-grant the budget. A shared abandoned flag, set when
  the wait expires, lets a not-yet-started task skip its RPC so the queue drains
  fast. A non-positive timeout launches nothing at all.
- Each slot is claimed via an atomic exchange BEFORE any sync RPC, so exactly one
  of the task and the inline submit-failure path owns the RPC, the result slot,
  and the latch count-down; an enqueue-then-fail task a later worker picks up
  loses the claim and cannot fire a sync for an already-settled query.
- The capture loop consumes each tablet's recorded fallback reason BEFORE its own
  get_tablet, and a worker-side tablet-load failure publishes a reason instead of
  leaving its slot empty, so no fallback route can push the synchronous
  cache-miss meta-service load onto the admission thread outside the deadline.

Cloud MOW write-back and mixed-version:
- BE no longer keys write-back on the raw prefer-cached knob for cloud MOW. FE
  resolves the selected index MOW state before the knob gate and reports it via a
  new optional field TQueryCacheParam.is_merge_on_write, and BE keeps write-back
  for the version-exact MOW read. The optional field is the mixed-version guard:
  old FE to new BE reads its default false and takes the conservative branch, new
  FE to old BE ignores it.

Tests and regression determinism:
- The regression stale-hit and fallback metric checks are gated to the
  shared-nothing path, sampling included; an aggregated BE-local counter cannot
  prove a specific cloud query used a stale entry when routing is
  topology-dependent. Cloud correctness is proven by result consistency plus
  deterministic BE unit tests.
- New BE tests: pool-rejects-submit fallback, rejection-plus-cache-miss proving
  zero admission-thread meta loads, worker-load-failure proving a single
  worker-side load, non-cloud-engine fallback, engine-stopped fallback,
  decision-sync timeout fallback, cloud MOW prefer write-back, and cloud
  sync-completeness history-rewrite detection.
@asdf2014

Copy link
Copy Markdown
Member Author

run buildall

@asdf2014

Copy link
Copy Markdown
Member Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes.

One new inline comment flags the cross-fragment presync stampede: fragment-local decision maps do not coalesce identical stale-key work at the BE-global cache/pool boundary. The remaining blocking defects are already precisely anchored in existing discussions, so I did not duplicate them:

  • P1: require an independent delete-bitmap completeness watermark. A cloud MOW tablet can be cold-loaded through version N with sync_delete_bitmap=false; the later bitmap-enabled presync then returns on _max_version >= N alone. A rewrite marker in (C,N] can remain absent, so the incremental classifier treats a history rewrite as append-only, merges the cached old row with its replacement, and writes a poisoned version-N cache entry. The new tests either force the sync or hand-install the bitmap and do not cover rowsets-current/bitmap-missing.
  • P1: make the freshness/prefer behavior safe across rolling FE/BE upgrades. Optional is_merge_on_write=false is structurally wire-compatible but does not protect either behavior boundary: an old FE can still request the new BE's exact-delta path while a warmed-read knob is active, and a new FE can send a MISS to an old BE whose unconditional write-back path stamps a potentially inexact scan result with the requested version.
  • The task ownership and shutdown portion of the presync lifecycle thread is fixed by the bounded engine-owned pool and shared state. Its admission-latency portion remains: fragment preparation waits synchronously for up to two seconds on a brpc_light worker during a meta-service brownout.

Critical checkpoint conclusions:

  • Goal and proof: the change successfully enables cloud DUP/same-version MOW incremental decisions and suppresses unsafe same-version cache fills under freshness/prefer options, with broad unit and regression coverage. It does not yet prove cloud MOW delete-bitmap completeness, rolling-version safety, or globally coalesced bounded admission, so the overall goal is incomplete.
  • Scope and clarity: all 17 changed files are related to incremental query-cache classification, its bounded cloud presync, protocol signal, metrics, and tests. The implementation is generally well explained and focused.
  • Concurrency and thread safety: each fragment-local decision map is locked only for lookup/publication while metadata/RPC work stays outside the lock. The fan-out uses per-slot atomics, shared latch/result ownership, and a bounded pool; no lock-order or deadlock defect was found. CacheSource and OlapScan local states are prepared sequentially within one fragment instance, but separate concurrent fragment contexts have private maps while sharing QueryCache::instance() and the same presync pool; that real production boundary permits the newly reported same-key stampede. Synchronous blocking of the light admission pool also remains, as noted above.
  • Lifecycle: the new pool is engine-owned, rejects/clears queued work on shutdown, joins running callbacks before tablet/meta dependencies are destroyed, and timed-out callbacks retain shared slot/latch state. Worker threads receive the normal default thread context. No circular ownership or cross-translation-unit static initialization issue was found.
  • Configuration: query_cache_decision_sync_timeout_ms is dynamic and each invocation observes it; non-positive values disable cloud incremental safely. Pool width and queue capacity are startup-only, which matches pool construction, and invalid values fail loudly. The timeout still needs an execution model that does not block light admission workers.
  • Compatibility: Thrift field addition 9 is optional and preserves decoding, but behavior is not safe in either mixed-version direction described above. This is blocking.
  • Parallel paths and conditions: local storage remains exact and does not apply cloud-only knobs; cloud DUP and MOW paths were both traced; selected-index MOW derivation and the same-version write-back conditions match storage capture semantics. The missing bitmap watermark is the parallel metadata-state path not covered by the new condition.
  • Tests and expected results: FE tests cover selected-index MOW and both knobs; BE tests cover write-back gates, cloud success/fallback, pool rejection, timeout, fan-out, and MOW rewrite detection; the regression test adds correctness/metric phases and correctly gates topology-dependent cloud metrics. Missing negative cases are rowsets-current/bitmap-missing, both rolling-version matrices, and two distinct runtimes contending for one stale global key while an unrelated key seeks admission. No generated result file needed changing. Per the review contract I did not run local builds or tests; formatter/checkstyle and Cloud UT pass, macOS BE UT failed in environment setup due the Java-version mismatch, and BE UT/FE UT/compile were still pending at review time.
  • Observability: stale-hit, fallback, and presync-time metrics plus fallback reasons provide useful coverage without adding hot-path INFO logging. No further metric is required for the reviewed behavior.
  • Persistence and transactions: no EditLog, durable metadata format, transaction, or failover state is changed. Query-cache write-back is ephemeral, but the blocking correctness paths can still poison or misuse cached results.
  • Data writes and crash behavior: there are no storage-engine data writes. Per-runtime decision publication and pinned-handle ownership are safe; pool shutdown does not leave callbacks using destroyed engine state.
  • FE-to-BE variables: the sole current FE construction path sets allow_incremental and is_merge_on_write, and same-version propagation is complete. Mixed-version semantics remain unresolved because the new behavior cannot be enforced by the old endpoint.
  • Performance: the fixed-width, bounded queue caps meta-service concurrency and backlog; abandoned tasks skip new RPCs. A large instance performs one job per tablet, and concurrent identical fragments can submit that entire fan-out repeatedly because coalescing is fragment-local; the tablet lock acts only after pool admission. This avoidable queue amplification and the synchronous light-pool wait are availability risks.
  • Other checks: status failures are converted to conservative full recomputation with tablet-level reasons; shared ownership is safe; no nullable-column or unrelated storage-format concern applies.

Focus response: no additional user-specified focus area was provided; I completed the full changed-file review.

CloudStorageEngine* engine_ptr = engine;
for (size_t i = 0; i < scan_ranges.size(); ++i) {
int64_t tablet_id = scan_ranges[i].scan_range.palo_scan_range.tablet_id;
Status submit_st = pool.submit_func([tablet_id, current_version, abandoned, i, engine_ptr,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Coalesce presync across fragment runtimes

QueryCacheRuntime only coalesces inside one PFC, but each concurrent query fragment has a private decision map while all of them read the BE-global QueryCache::instance(). Under default single-primary placement (or a one-BE compute group), identical query-cache queries reach the same BE and stale key, so each runtime independently executes this per-tablet submit loop. While metadata syncs are slow, three default-limit 768-tablet instances submit 2304 jobs into the default 16-worker/2048-pending pool: at least 240 submissions reject even though any one fan-out fits, forcing avoidable full recomputation and denying unrelated keys admission. The tablet sync lock acts only after pool admission. Please single-flight sync completion globally by (cache_key, current_version) while retaining per-query deadlines, fallback, and delta-source capture, and test distinct runtimes plus an unrelated key.

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 88.89% (16/18) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 29527 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 90896ddbf09d6b61df902215a95814e18e141eef, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17639	4120	4238	4120
q2	2011	309	198	198
q3	10764	1416	832	832
q4	4727	474	340	340
q5	8117	873	574	574
q6	313	172	141	141
q7	837	839	606	606
q8	10474	1603	1601	1601
q9	5887	4336	4364	4336
q10	6819	1745	1474	1474
q11	512	341	327	327
q12	762	582	443	443
q13	18075	3357	2709	2709
q14	265	256	252	252
q15	q16	789	780	712	712
q17	1021	1049	911	911
q18	6967	5844	5601	5601
q19	1393	1268	1054	1054
q20	797	670	555	555
q21	5570	2645	2443	2443
q22	407	354	298	298
Total cold run time: 104146 ms
Total hot run time: 29527 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4426	4286	4296	4286
q2	287	331	210	210
q3	4587	4911	4460	4460
q4	2036	2137	1344	1344
q5	4358	4213	4267	4213
q6	226	177	126	126
q7	2198	1935	1533	1533
q8	2440	2193	2100	2100
q9	7879	7710	7785	7710
q10	4699	4634	4208	4208
q11	739	427	385	385
q12	730	781	536	536
q13	3292	3639	2995	2995
q14	314	304	267	267
q15	q16	707	763	632	632
q17	1353	1320	1348	1320
q18	7898	7359	6794	6794
q19	1089	1103	1089	1089
q20	2219	2195	1960	1960
q21	5211	4551	4376	4376
q22	521	467	406	406
Total cold run time: 57209 ms
Total hot run time: 50950 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 178785 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 90896ddbf09d6b61df902215a95814e18e141eef, data reload: false

query5	4330	628	486	486
query6	474	218	202	202
query7	4886	560	342	342
query8	339	191	177	177
query9	8826	4045	4062	4045
query10	465	366	296	296
query11	5916	2339	2120	2120
query12	154	100	102	100
query13	1268	590	422	422
query14	6222	5128	4887	4887
query14_1	4211	4193	4203	4193
query15	224	205	179	179
query16	1040	475	459	459
query17	1151	709	596	596
query18	2749	468	358	358
query19	216	196	155	155
query20	113	107	107	107
query21	241	161	134	134
query22	13602	13442	13275	13275
query23	17375	16441	16147	16147
query23_1	16251	16233	16269	16233
query24	7480	1724	1269	1269
query24_1	1309	1309	1266	1266
query25	568	465	395	395
query26	1346	357	215	215
query27	2570	613	377	377
query28	4442	1987	1989	1987
query29	1097	632	491	491
query30	343	264	227	227
query31	1131	1096	986	986
query32	114	66	64	64
query33	577	322	261	261
query34	1187	1198	668	668
query35	774	788	677	677
query36	1193	1213	1040	1040
query37	161	107	98	98
query38	1884	1712	1669	1669
query39	900	881	847	847
query39_1	845	852	855	852
query40	253	165	148	148
query41	78	72	72	72
query42	97	95	93	93
query43	321	328	277	277
query44	1403	776	772	772
query45	199	181	176	176
query46	1036	1158	712	712
query47	2195	2142	2026	2026
query48	404	423	302	302
query49	610	424	314	314
query50	1070	442	330	330
query51	10838	11058	10868	10868
query52	92	89	77	77
query53	272	275	212	212
query54	292	251	236	236
query55	77	73	75	73
query56	331	313	300	300
query57	1324	1301	1212	1212
query58	318	323	256	256
query59	1585	1597	1395	1395
query60	307	276	257	257
query61	159	154	154	154
query62	555	494	431	431
query63	241	204	207	204
query64	2783	1032	855	855
query65	4747	4636	4621	4621
query66	1795	502	388	388
query67	29346	29279	29095	29095
query68	3130	1638	979	979
query69	423	324	260	260
query70	1080	956	945	945
query71	379	337	329	329
query72	3039	2684	2358	2358
query73	826	821	403	403
query74	5092	4924	4759	4759
query75	2540	2592	2139	2139
query76	2347	1179	730	730
query77	352	374	286	286
query78	11921	11770	11494	11494
query79	1363	1162	741	741
query80	1332	546	483	483
query81	533	332	282	282
query82	652	158	125	125
query83	380	317	295	295
query84	276	152	132	132
query85	969	602	539	539
query86	416	280	293	280
query87	1822	1819	1746	1746
query88	3686	2776	2773	2773
query89	435	390	325	325
query90	1918	190	202	190
query91	200	193	169	169
query92	64	63	56	56
query93	1668	1457	997	997
query94	719	355	339	339
query95	804	573	484	484
query96	1096	761	322	322
query97	2686	2668	2488	2488
query98	221	202	205	202
query99	1086	1114	977	977
Total cold run time: 264651 ms
Total hot run time: 178785 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 25.47 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 90896ddbf09d6b61df902215a95814e18e141eef, data reload: false

query1	0.01	0.01	0.01
query2	0.14	0.08	0.08
query3	0.37	0.25	0.24
query4	1.61	0.24	0.24
query5	0.33	0.32	0.31
query6	1.16	0.67	0.66
query7	0.04	0.01	0.01
query8	0.10	0.07	0.07
query9	0.50	0.38	0.39
query10	0.57	0.57	0.57
query11	0.32	0.18	0.17
query12	0.31	0.19	0.19
query13	0.52	0.52	0.51
query14	0.93	0.92	0.93
query15	0.68	0.59	0.57
query16	0.40	0.39	0.39
query17	0.99	0.99	1.02
query18	0.31	0.29	0.29
query19	1.88	1.79	1.84
query20	0.02	0.02	0.01
query21	15.46	0.38	0.32
query22	4.72	0.13	0.14
query23	15.82	0.50	0.30
query24	2.51	0.62	0.43
query25	0.15	0.11	0.09
query26	0.73	0.26	0.21
query27	0.11	0.10	0.10
query28	3.56	0.87	0.51
query29	12.46	4.24	3.32
query30	0.38	0.27	0.27
query31	2.77	0.62	0.32
query32	3.22	0.60	0.48
query33	2.99	2.93	3.03
query34	15.81	4.06	3.35
query35	3.29	3.25	3.25
query36	0.64	0.52	0.51
query37	0.12	0.09	0.09
query38	0.08	0.07	0.06
query39	0.07	0.06	0.06
query40	0.20	0.19	0.16
query41	0.12	0.08	0.07
query42	0.09	0.05	0.05
query43	0.07	0.07	0.06
Total cold run time: 96.56 s
Total hot run time: 25.47 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 91.82% (146/159) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.00% (30504/40671)
Line Coverage 59.15% (336373/568696)
Region Coverage 55.86% (282169/505098)
Branch Coverage 57.21% (125293/219014)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants