Skip to content

[improvement](cloud) support memtable on sink node - #68365

Open
mymeiyi wants to merge 3 commits into
apache:masterfrom
mymeiyi:cloud-load-1
Open

mymeiyi wants to merge 3 commits into
apache:masterfrom
mymeiyi:cloud-load-1

Conversation

@mymeiyi

@mymeiyi mymeiyi commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

No description provided.

### What problem does this PR solve?

Problem Summary: Packed slice collection depends only on a closed file writer,
its logical path, and the destination rowset metadata, but was a private method
of CloudRowsetWriter. Move it to RowsetMeta::collect_packed_slice_location and
reuse it for existing Cloud segment and index collection without changing
collection timing. Preserve skipping unfinished and non-packed files. Require
a nonempty packed object path after a successful packed-location lookup,
replacing the previous silent skip with an invariant assertion.

Move the associated RowsetMetaPackedFileTest coverage with this refactor:
completed data/index files, logical paths distinct from writer URIs, repeated
collection, serialization, non-packed files, and missing mappings. Memtable
forwarding call sites and MOW collection timing changes remain in subsequent
commits.

During rebase, retain the upstream writer-owned packed slice lookup so global
index cleanup cannot invalidate metadata collection. Adapt the unit coverage
to real PackedFileWriter handles, including incomplete writers, direct files,
serialization, repeated collection, and missing-handle invariant failures.

### Release note

None

### Check List (For Author)

- Test: Unit tests adapted but not run, per request. No build or service execution. Conflict-resolution files passed clang-format 16, format checks, build hygiene, and Git whitespace checks.
- Behavior changed: Yes; an empty packed object path after successful lookup is an invariant failure instead of a silent skip
- Does this need documentation: No
### What problem does this PR solve?

Problem Summary: Cloud MOW loads build temporary rowsets in asynchronous delete
bitmap tasks while other flushes can still add or close file writers. Building
those temporary rowsets previously traversed all segment and index writer
collections without their locks to collect packed mappings. Collect only the
current segment's mapping after its writer closes, and reserve full collection
for final rowset construction after flushes finish. Pass the segment ID through
_build_tmp and update the existing unit-test wrapper and call accordingly.

CloudRowsetWriter::build also collected the same mappings a second time directly
after _build_rowset_meta had already collected them. Remove that redundant call.
These issues affect existing Cloud load paths independently of memtable forwarding.
Forwarded-file snapshots and direct-upload logic remain in the following feature.

### Release note

Avoid concurrent traversal of file writer collections during Cloud MOW packed
file loads and eliminate duplicate packed mapping collection at finalization.

### Check List (For Author)

- Test: Static call-site review and git diff --check; existing TmpRowsetUsesCompletedSegmentIds test adapted to the signature change. No builds or runtime tests at user request; concurrent execution was not reproduced during this split.
- Behavior changed: Yes; temporary rowsets collect only the current segment's packed mapping and final rowsets collect all mappings once
- Does this need documentation: No
Copilot AI lite review requested due to automatic review settings September 22, 2026 04:00
@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?

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Address transaction/vault propagation, empty packed-file handling, and unordered regression queries.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 Medium severity

Open (2)
What changed in this PR

Adds cloud-mode memtable-on-sink support with streamed rowset handling, metadata propagation, cloud commits, and regression coverage.

Changes:

  • Enables cloud sink memtables for pipeline and broker loads.
  • Propagates transaction, vault, and stream metadata.
  • Adds packed-file handling and unit/regression tests.
File Summary
regression-test/​suites/​cloud_p0/​test_cloud_memtable_on_sink.groovy Cloud sink-memtable tests
regression-test/​suites/​cloud_p0/​test_cloud_memtable_mow_forward.groovy MoW forwarding tests
regression-test/​data/​cloud_p0/​test_cloud_memtable_on_sink.out Expected test results
regression-test/​data/​cloud_p0/​test_cloud_memtable_mow_forward.out Expected test results
gensrc/​proto/​internal_service.proto Load-stream metadata fields
fe/​fe-core/​src/​main/​java/​org/​apache/​doris/​load/​loadv2/​BrokerLoadJob.java Enables cloud broker sink memtables
be/​test/​storage/​rowset/​rowset_meta_test.cpp Packed-location unit tests
be/​test/​storage/​rowset/​beta_rowset_test.cpp Delete-bitmap failure tests
be/​src/​storage/​rowset/​rowset_meta.h Packed-location API
be/​src/​storage/​rowset/​rowset_meta.cpp Packed-location handling
be/​src/​storage/​rowset/​beta_rowset_writer.h Temporary-rowset API updates
be/​src/​storage/​rowset/​beta_rowset_writer.cpp Streamed rowset metadata handling
be/​src/​load/​channel/​load_stream.h Load metadata state
be/​src/​load/​channel/​load_stream.cpp Metadata propagation
be/​src/​load/​channel/​load_stream_writer.cpp Cloud rowset writing
be/​src/​exec/​sink/​writer/​vtablet_writer_v2.h Transaction and vault state
be/​src/​exec/​sink/​writer/​vtablet_writer_v2.cpp Enriched load streams
be/​src/​exec/​sink/​load_stream_stub.h Stream-open interface updates
be/​src/​exec/​sink/​load_stream_stub.cpp Stream request metadata
be/​src/​exec/​pipeline/​pipeline_fragment_context.cpp Enables cloud sink memtables
be/​src/​cloud/​cloud_rowset_writer.h Shared metadata collection
be/​src/​cloud/​cloud_rowset_writer.cpp Packed metadata collection
be/​src/​cloud/​cloud_rowset_builder.h Cloud transaction commit API
be/​src/​cloud/​cloud_rowset_builder.cpp Cloud transaction commit

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread be/src/exec/sink/writer/vtablet_writer_v2.cpp
Comment thread be/src/storage/rowset/rowset_meta.cpp
@mymeiyi

mymeiyi commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

/review

@github-actions

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: Codex completed, but no new pull request review was submitted for the current head SHA.
Workflow run: https://github.com/apache/doris/actions/runs/35686102105

Please inspect the workflow logs and rerun the review after the underlying issue is resolved.

@mymeiyi

mymeiyi commented Sep 22, 2026

Copy link
Copy Markdown
Contributor 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: the static review found four PR-attributable issues: mixed-version sink incompatibility, loss of the cloud empty-rowset metadata-skip lifecycle, serialized metadata RPCs under stream locks, and stale regression output. The two existing inline threads remain valid duplicate fences and were not repeated.

Critical-checkpoint conclusions:

  • Goal and proof: the change enables memtable-on-sink for cloud loads and covers packed/MoW paths, but the checked-in tests do not prove rolling upgrades, sparse many-bucket loads, or many-tablet close behavior; one expected-output file is not the output of the current suite.
  • Scope and reuse: the diff is focused, but the new receiver bypasses specialized lifecycle/orchestration already present in CloudDeltaWriter and CloudTabletsChannel.
  • Concurrency: per-tablet flush ordering and MoW snapshot lifetimes are sound in the inspected paths. No new lock-order deadlock was found, but cloud sync/prepare/commit RPCs now run serially while IndexStream/LoadStream locks are held.
  • Lifecycle and static initialization: packed writer ownership, temporary-rowset capture, cancellation, and nonempty commit/cache/stat ordering were traced and found consistent. Empty-rowset handling is not consistent with the established path. No cross-TU/static-initialization change is involved.
  • Configuration: no new config was added. The existing default-enabled skip_writing_empty_rowset_metadata setting is bypassed by the new receiver path.
  • Compatibility: the optional protobuf fields are wire-compatible, but feature/protocol selection is not semantically safe during a rolling BE upgrade.
  • Parallel paths and conditions: partial update, V1 inverted index, and row-binlog fallbacks remain gated. The legacy cloud path's empty handling and bounded commit concurrency were not carried into the new path.
  • Tests and results: unit and Docker regression coverage was added, but it lacks mixed-version, sparse multi-bucket metadata, and many-tablet latency/fault cases. test_cloud_memtable_on_sink.out contains unreachable blocks and must be regenerated or matched by restored cases.
  • Observability: existing profiles, logs, and commit latency metrics are adequate for the reviewed flow; no separate observability blocker was found.
  • Transactions, persistence, and crash behavior: no FE EditLog change is involved. Cloud prepare/build/bitmap/commit behavior was traced; apart from empty-rowset metadata and rolling-upgrade receiver aborts, no additional atomicity or cleanup defect was substantiated.
  • FE/BE variables: the direct stream-open fields propagate through the reviewed path. The already-open inline thread covers the separate internal expiration/vault omission, so it is not duplicated here.
  • Performance: empty metadata amplification and lock-scoped serial meta-service RPCs are blocking concerns. No additional CPU, memory, or mapping issue was substantiated.
  • Other: packed metadata and MoW physical-segment ordering converged with no new finding beyond the existing zero-byte packed-index thread.

User focus: no additional focus was supplied. Validation was static only as required; no build or test was run, and author/CI claims were not treated as independent execution evidence.

if (state->query_options().enable_memtable_on_sink_node &&
!_has_inverted_index_v1_or_partial_update(thrift_sink.olap_table_sink) &&
!_has_row_binlog(thrift_sink.olap_table_sink) && !config::is_cloud_mode()) {
!_has_row_binlog(thrift_sink.olap_table_sink)) {

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] Add a mixed-version capability fence before enabling the cloud V2 sink. During a rolling upgrade this per-BE condition makes new fragment instances choose the V2/load-stream protocol while old instances choose the legacy tablets channel. A new sender can also target an old tablet-location BE; that receiver's LoadStreamWriter unconditionally calls storage_engine().to_local(), whose type check aborts in cloud mode. The optional request fields do not negotiate support. Gate this at the coordinator/minimum BE version (or negotiate and fall back) so every sender and receiver in one load uses a compatible protocol.

Comment thread be/src/cloud/cloud_rowset_builder.cpp Outdated
// FIXME(plat1ko): No `commit_txn` operation in cloud mode, need better abstractions
RETURN_IF_ERROR(static_cast<RowsetBuilder*>(_rowset_builder.get())->commit_txn());

RETURN_IF_ERROR(_rowset_builder->commit_txn());

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] Avoid running the cloud metadata RPCs serially under the load-stream locks. This call is reached for every tablet from IndexStream::close() while its _lock is held, and that close itself runs under LoadStream::_lock; the first append also holds the index lock across sync_rowsets() and prepare_rowset(). A many-tablet load therefore pays the sum of all prepare/commit RPC latencies and one slow tablet head-of-line blocks unrelated tablets. CloudTabletsChannel already uses batch initialization and bounded bthread_fork_join(..., 10) for this lifecycle. Move remote work out of the locks and preserve bounded concurrency.

Comment thread regression-test/data/cloud_p0/test_cloud_memtable_on_sink.out Outdated
### What problem does this PR solve?

Problem Summary: Cloud loads previously excluded the memtable-on-sink path. Allow eligible full-row DUPLICATE, AGGREGATE, UNIQUE MOR, and UNIQUE MOW loads to build memtables and segments on sink BEs, then forward segment and index files to the target BE for object storage upload and rowset commit. Retain the restrictions for partial updates, V1 indexes, and row binlog.

Pass transaction expiration, storage vault, and cache policy through stream-open requests. Select CloudRowsetBuilder in LoadStreamWriter, collect forwarded packed-file mappings and file sizes, and snapshot temporary rowset metadata before asynchronous MOW bitmap calculation on the target BE.

Honor skip_writing_empty_rowset_metadata for untouched tablets by setting the policy before initialization and skipping prepare/commit RPCs while preserving empty markers and statistics. Close cloud tablet writers with concurrency 10 after pre-close, collecting all tablet results even when some fail. Preserve local-mode close behavior and existing locking.

Add coverage for DUP/AGG/MOR/MOW, packed files, Stream Load, Broker Load, async Group Commit internal writer profiles, duplicate-key checks, cold reads, failed load invisibility and retry, and partial-update loading results. Add BE coverage for bitmap snapshot failures, empty-rowset lifecycle, and bounded concurrent close with mixed results. Align regression output blocks with the file-forwarding suite.

### Release note

Cloud loads can enable memtable-on-sink for eligible full-row DUPLICATE, AGGREGATE, and UNIQUE MOR/MOW tables. Sink BEs construct files and target BEs upload them and calculate MOW bitmaps. Empty tablets honor the existing metadata-skip configuration, and cloud tablet closes run with bounded concurrency.

### Check List (For Author)

- Test: Static call-site review, clang-format 16 checks, build hygiene checks, and source git diff --check passed. BE unit tests and regression cases added or updated; no compilation, source generation, or runtime tests performed during these changes, as requested. Unused regression output blocks removed without changing retained results; existing output-file trailing separators preserved.
- Behavior changed: Yes; eligible Cloud loads use file forwarding, preserve empty metadata skipping, and close tablet writers concurrently.
- Does this need documentation: Yes; design documents excluded from this commit at user request.
@mymeiyi

mymeiyi commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17615	3935	3943	3935
q2	2180	376	321	321
q3	10067	1410	820	820
q4	4759	485	349	349
q5	8195	839	547	547
q6	305	174	137	137
q7	838	794	597	597
q8	10629	1542	1644	1542
q9	5899	4243	4198	4198
q10	6877	1352	1040	1040
q11	443	277	247	247
q12	649	422	292	292
q13	18076	2619	2003	2003
q14	258	261	243	243
q15	q16	739	715	663	663
q17	1778	1149	1032	1032
q18	6563	5615	5538	5538
q19	1178	1278	1024	1024
q20	492	383	264	264
q21	5398	2925	2762	2762
q22	420	343	292	292
Total cold run time: 103358 ms
Total hot run time: 27846 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4258	4188	4273	4188
q2	703	564	528	528
q3	4464	4866	4341	4341
q4	2210	2355	1455	1455
q5	4230	4219	4124	4124
q6	226	172	125	125
q7	1701	1685	1475	1475
q8	2204	1916	1887	1887
q9	6889	6934	6869	6869
q10	3660	3579	3121	3121
q11	550	422	389	389
q12	726	715	508	508
q13	2305	2647	2006	2006
q14	283	289	257	257
q15	q16	677	704	607	607
q17	7370	6784	6714	6714
q18	11946	11142	11834	11142
q19	1130	1028	1024	1024
q20	2229	2218	1935	1935
q21	5030	4128	4358	4128
q22	519	477	418	418
Total cold run time: 63310 ms
Total hot run time: 57241 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 153311 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 cc5cea49d1b652227b3af22c88e3bb7343ce0df8, data reload: false

query5	4323	606	440	440
query6	436	211	190	190
query7	4803	569	290	290
query8	315	187	167	167
query9	8791	3959	3983	3959
query10	440	319	253	253
query11	5856	3554	3242	3242
query12	143	91	84	84
query13	1248	574	426	426
query14	6500	4661	4252	4252
query14_1	3988	3968	3967	3967
query15	201	199	181	181
query16	1024	496	474	474
query17	1113	698	544	544
query18	2437	468	349	349
query19	215	186	143	143
query20	103	82	88	82
query21	222	139	118	118
query22	13049	13083	12777	12777
query23	13994	13051	12626	12626
query23_1	12577	12509	12656	12509
query24	7184	1142	676	676
query24_1	704	759	709	709
query25	551	444	383	383
query26	1251	323	170	170
query27	2666	549	336	336
query28	4599	1991	1973	1973
query29	1701	714	517	517
query30	297	223	186	186
query31	888	760	628	628
query32	150	94	96	94
query33	506	304	250	250
query34	1173	1093	624	624
query35	716	746	640	640
query36	807	822	720	720
query37	146	106	92	92
query38	1837	1775	1714	1714
query39	700	671	628	628
query39_1	653	661	662	661
query40	223	121	105	105
query41	68	65	66	65
query42	96	94	92	92
query43	333	350	299	299
query44	1375	721	729	721
query45	182	179	172	172
query46	1092	1182	704	704
query47	1491	1510	1411	1411
query48	391	432	303	303
query49	579	405	298	298
query50	964	371	244	244
query51	10803	10590	10616	10590
query52	88	91	74	74
query53	247	265	178	178
query54	256	206	185	185
query55	83	73	69	69
query56	228	205	210	205
query57	1477	1525	1482	1482
query58	283	266	270	266
query59	1997	2077	1883	1883
query60	286	242	224	224
query61	151	154	140	140
query62	395	340	266	266
query63	215	175	175	175
query64	2832	999	798	798
query65	3491	3416	3414	3414
query66	1800	415	309	309
query67	19980	20291	19841	19841
query68	3055	1553	918	918
query69	415	318	267	267
query70	915	838	825	825
query71	296	224	219	219
query72	2735	2519	2275	2275
query73	796	761	431	431
query74	4612	4482	4320	4320
query75	2287	2305	1921	1921
query76	2344	1128	755	755
query77	360	396	291	291
query78	9093	8950	8484	8484
query79	1201	1275	725	725
query80	529	490	398	398
query81	534	333	281	281
query82	265	167	130	130
query83	221	232	211	211
query84	278	150	120	120
query85	873	537	455	455
query86	283	243	237	237
query87	1981	1983	1860	1860
query88	3636	2768	2764	2764
query89	325	288	243	243
query90	2135	179	180	179
query91	168	155	123	123
query92	106	91	85	85
query93	1446	1478	872	872
query94	524	298	312	298
query95	658	453	335	335
query96	1116	816	328	328
query97	2412	2458	2297	2297
query98	174	159	144	144
query99	715	717	617	617
Total cold run time: 235890 ms
Total hot run time: 153311 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.09	0.05	0.04
query3	0.26	0.14	0.14
query4	1.61	0.15	0.14
query5	0.24	0.22	0.22
query6	1.16	0.93	0.95
query7	0.04	0.01	0.01
query8	0.05	0.05	0.04
query9	0.39	0.33	0.34
query10	0.56	0.54	0.55
query11	0.20	0.14	0.15
query12	0.18	0.15	0.14
query13	0.47	0.46	0.47
query14	0.99	0.94	0.94
query15	0.60	0.58	0.59
query16	0.31	0.31	0.32
query17	1.12	1.11	1.05
query18	0.22	0.21	0.20
query19	2.05	1.91	1.93
query20	0.02	0.02	0.01
query21	15.47	0.21	0.14
query22	4.88	0.06	0.06
query23	16.12	0.31	0.12
query24	2.97	0.44	0.34
query25	0.10	0.04	0.03
query26	0.77	0.22	0.15
query27	0.04	0.04	0.03
query28	3.46	0.76	0.34
query29	12.51	4.01	3.18
query30	0.27	0.15	0.18
query31	2.77	0.55	0.32
query32	3.21	0.60	0.48
query33	3.20	3.20	3.17
query34	15.56	3.93	3.28
query35	3.24	3.21	3.22
query36	0.56	0.42	0.39
query37	0.09	0.06	0.06
query38	0.05	0.04	0.04
query39	0.04	0.03	0.03
query40	0.17	0.16	0.14
query41	0.10	0.04	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.23 s
Total hot run time: 23.89 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 100.00% (40/40) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 63.94% (29760/46542)
Line Coverage 48.61% (310183/638128)
Region Coverage 44.14% (250165/566746)
Branch Coverage 45.69% (116258/254432)

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100.00% (40/40) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 76.30% (34385/45068)
Line Coverage 61.22% (386212/630836)
Region Coverage 57.58% (324988/564451)
Branch Coverage 58.42% (148167/253637)

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.

3 participants