Skip to content

[refine](column) separate mutable subcolumn mutation from read-only traversal#64905

Open
Mryange wants to merge 3 commits into
apache:masterfrom
Mryange:column-subcolumn-cow-refine
Open

[refine](column) separate mutable subcolumn mutation from read-only traversal#64905
Mryange wants to merge 3 commits into
apache:masterfrom
Mryange:column-subcolumn-cow-refine

Conversation

@Mryange

@Mryange Mryange commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Column wrappers used for_each_subcolumn for both read-only traversal and mutable subcolumn detachment during COW mutation. This mixed two different contracts in one callback API and forced typed subcolumns such as ColumnNullable::_null_map, ColumnArray::offsets, and ColumnMap::offsets_column to move through temporary base IColumn::WrappedPtr bridges.

Root cause: the mutable callback accepted IColumn::WrappedPtr&, but several subcolumns are stored as strongly typed wrappers. Binding typed wrapper references to the base wrapper callback is unsafe, so each implementation needed ad-hoc move/defer/cast code.

This PR keeps for_each_subcolumn as a const read-only traversal API and adds mutate_subcolumns() for the COW mutation path. Common mutate_subcolumn helpers handle generic and strongly typed subcolumns, so ColumnArray, ColumnMap, ColumnNullable, ColumnStruct, and ColumnVariant can detach children without exposing a mutable traversal callback. The added BEUT cases also verify that mutating exclusive subcolumns does not introduce an extra copy.

Release note

None

Check List (For Author)

  • Test

    • Regression test
    • Unit Test
    • Manual test (add detailed scripts or steps below)
    • 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.
  • Does this need documentation?

    • No.
    • Yes.

Check List (For Reviewer who merge this PR)

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

@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?

@Mryange

Mryange commented Jun 26, 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.

Review result: request changes for one test coverage gap in the core column COW refactor.

Critical checkpoint conclusions:

  • Goal: the PR separates read-only subcolumn traversal from recursive COW mutation. The code mostly accomplishes that by keeping for_each_subcolumn const-only and routing IColumn::mutate through mutate_subcolumns().
  • Scope/focus: the source change is small and focused on BE column wrappers, with tests added for array and nullable COW behavior.
  • Concurrency/lifecycle: no new threads, locks, static initialization, persistence, transaction, or configuration behavior are introduced.
  • Compatibility/protocol: no serialization format, FE/BE protocol, or function symbol compatibility change found.
  • Parallel paths: array, nullable, map, struct, const, and variant wrapper paths were checked. The remaining issue is that the distinct map enumeration path lacks focused mutation coverage.
  • Error handling/memory: no ignored Status or new memory ownership issue found in the changed code.
  • Tests: git diff --check is clean for the PR file set. Formatter/style CI is green. I could not run BE UT locally because thirdparty/installed is absent in this runner. The current macOS BE-UT CI job fails before compiling Doris with ERROR: The JAVA version is 25, it must be JDK-17, so I did not treat that as PR-caused.

User focus: no additional user-provided focus points were present.

Subagent conclusions: optimizer-rewrite reported no candidates. tests-session-config proposed TEST-1; I verified and accepted the ColumnMap portion as MAIN-1 for an inline comment. Convergence round 1 ended with both live subagents reporting NO_NEW_VALUABLE_FINDINGS for the same ledger and one-comment final set.

callback(keys_column);
callback(values_column);
callback(offsets);
void mutate_subcolumns() override {

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.

This COW refactor changes ColumnMap from the old callback/defer path to a class-specific mutate_subcolumns() that must enumerate all three children (keys_column, values_column, and typed offsets_column). The new tests cover array and nullable, but there is no focused test that mutates a shared/exclusive ColumnMap and verifies all three child pointers are detached or preserved correctly. A missed or wrong entry in this method would compile and leave one map child aliased across mutation, so please add a BE unit test analogous to the new array/nullable cases for ColumnMap.

@Mryange

Mryange commented Jun 28, 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.

I found one remaining review issue: the COW refactor still lacks direct coverage for the shared-detach path on ColumnArray, and for the new ColumnConst/ColumnStruct mutation hooks. The existing ColumnMap review thread is already known context and current head has map tests, so I did not duplicate that comment.

Critical checkpoints:

  • Goal/test: the refactor is focused, but the changed composite-column mutation paths are not all directly proved by tests.
  • Scope: authoritative GitHub file list is limited to BE column COW code and BE column tests.
  • Concurrency/lifecycle/config/compatibility/persistence/data writes/session propagation: not involved in this PR scope.
  • Parallel paths: checked Array, Map, Nullable, Const, Struct, and Variant mutation paths; only the test gap below remains substantiated.
  • Test/results: git diff --check is clean. BE tests were not run because thirdparty/installed is missing in this checkout.

Subagent conclusions: tests-session-config proposed TEST-1, accepted as MAIN-1 and submitted below. optimizer-rewrite reported no optimizer/Nereids semantic issue. Convergence round 1 ended with both live subagents replying NO_NEW_VALUABLE_FINDINGS for the same MAIN-1-only comment set.

});
callback(offsets_column);
callback(data);
void mutate_subcolumns() override {

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.

This new hook still needs a shared-detach test. The added array COW test builds the array from moved mutable children and then calls IColumn::mutate(std::move(array)), so it only exercises the exclusive fast path; it would not catch a regression where the by-value/shared IColumn::mutate(array) path forgets to detach either the nested data or the typed offsets. Please add a small test analogous to the nullable/map shared tests that keeps aliases to both child columns, calls IColumn::mutate(array) without moving the source owner, and verifies the result detached both children while the aliases remain unchanged. Since this PR also adds mutate_subcolumns() hooks for ColumnConst and ColumnStruct, small direct mutate tests for those hooks would keep the COW refactor covered across all changed composite columns.

@Mryange

Mryange commented Jun 28, 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.

Review complete. I did not find a new distinct issue that needs an additional inline comment.

Critical checkpoint conclusions:

  • Goal and scope: the PR separates mutable subcolumn mutation from read-only traversal in BE column COW code. The implementation is focused on IColumn::mutate_subcolumns() and the composite column overrides for Array, Map, Nullable, Const, Struct, and Variant.
  • COW correctness: the new helper preserves recursive detach semantics. Typed child pointers for offsets/null maps are restored through concrete WrappedPtr conversions, and the remaining for_each_subcolumn callers are read-only traversal.
  • Parallel paths: Array, Map, Nullable, Const, Struct, and Variant mutation paths were checked. Variant already has clone_finalized_deep_copies_columns, which exercises IColumn::mutate(get_ptr()) and verifies subcolumns plus sparse/doc columns are copied.
  • Existing review context: the prior ColumnMap and Array/Const/Struct coverage comments are not duplicated. Current head adds the missing shared/exclusive COW tests for Array, Map, Const, and Struct, with Nullable covering the typed null-map path.
  • Concurrency/lifecycle/config/compatibility: no new threads, locks, static lifecycle, session/config, serialization, or protocol compatibility changes are introduced by the authoritative PR file set.
  • Tests and validation: the added BE unit tests cover the relevant shared and exclusive mutation paths. I ran git diff --check on the authoritative changed files and it was clean. I did not run BE unit tests because this runner has no thirdparty/installed and no existing BE test binaries/output build to execute.
  • User focus: no additional user-provided review focus was supplied.

Subagent conclusions:

  • optimizer-rewrite: no candidates; convergence round 1 returned NO_NEW_VALUABLE_FINDINGS.
  • tests-session-config: no candidates; convergence round 1 returned NO_NEW_VALUABLE_FINDINGS.
  • No subagent candidate became an inline comment; the only reviewed concerns were dismissed as duplicate existing threads or with code/test evidence in the shared ledger.

@Mryange

Mryange commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17632	4034	4011	4011
q2	2004	340	198	198
q3	10304	1439	832	832
q4	4711	468	331	331
q5	7672	878	570	570
q6	220	167	133	133
q7	804	847	628	628
q8	10428	1647	1649	1647
q9	6007	4542	4553	4542
q10	6837	1805	1530	1530
q11	455	275	240	240
q12	645	422	286	286
q13	18077	3474	2746	2746
q14	271	264	235	235
q15	q16	790	776	712	712
q17	936	995	1006	995
q18	6766	5763	5472	5472
q19	1159	1328	1020	1020
q20	498	388	264	264
q21	5604	2645	2458	2458
q22	432	371	305	305
Total cold run time: 102252 ms
Total hot run time: 29155 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4308	4258	4339	4258
q2	322	342	226	226
q3	4582	4962	4355	4355
q4	2061	2158	1379	1379
q5	4468	4287	4297	4287
q6	227	181	130	130
q7	1719	1866	1707	1707
q8	2553	2259	2071	2071
q9	8039	8120	8029	8029
q10	4835	4788	4339	4339
q11	571	412	371	371
q12	862	841	545	545
q13	3354	3572	3059	3059
q14	299	303	271	271
q15	q16	714	744	648	648
q17	1349	1320	1324	1320
q18	7974	7395	7017	7017
q19	1133	1096	1082	1082
q20	2230	2232	1945	1945
q21	5273	4631	4350	4350
q22	517	449	402	402
Total cold run time: 57390 ms
Total hot run time: 51791 ms

@hello-stephen

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

query5	4314	622	478	478
query6	431	185	171	171
query7	4818	539	304	304
query8	326	184	163	163
query9	8762	4105	4073	4073
query10	449	325	263	263
query11	5843	2361	2144	2144
query12	163	104	101	101
query13	1271	627	429	429
query14	6267	5368	4958	4958
query14_1	4279	4262	4263	4262
query15	214	195	177	177
query16	1011	445	422	422
query17	1103	702	556	556
query18	2526	460	329	329
query19	216	176	137	137
query20	110	103	104	103
query21	216	134	114	114
query22	13625	13705	13398	13398
query23	17195	16549	16175	16175
query23_1	16271	16234	16321	16234
query24	7522	1764	1317	1317
query24_1	1316	1306	1299	1299
query25	536	452	389	389
query26	1332	340	176	176
query27	2709	567	343	343
query28	4466	2017	2027	2017
query29	1074	627	496	496
query30	305	230	202	202
query31	1109	1093	957	957
query32	109	64	62	62
query33	530	326	257	257
query34	1171	1139	665	665
query35	773	794	714	714
query36	1435	1375	1185	1185
query37	146	109	88	88
query38	1875	1715	1647	1647
query39	911	910	893	893
query39_1	872	868	882	868
query40	215	124	98	98
query41	63	64	62	62
query42	89	85	85	85
query43	314	318	274	274
query44	1407	784	781	781
query45	202	185	177	177
query46	1093	1219	763	763
query47	2339	2325	2212	2212
query48	384	388	263	263
query49	581	426	307	307
query50	1053	368	264	264
query51	4437	4449	4263	4263
query52	79	79	70	70
query53	243	259	194	194
query54	262	214	196	196
query55	72	68	67	67
query56	223	218	216	216
query57	1414	1404	1309	1309
query58	233	210	213	210
query59	1539	1645	1386	1386
query60	274	247	225	225
query61	159	148	151	148
query62	719	649	583	583
query63	231	194	192	192
query64	2490	760	623	623
query65	4887	4765	4779	4765
query66	1770	462	335	335
query67	29014	28826	28629	28629
query68	3231	1501	967	967
query69	413	298	326	298
query70	1033	942	972	942
query71	279	234	215	215
query72	2857	2559	2302	2302
query73	847	789	432	432
query74	5090	4943	4759	4759
query75	2583	2527	2158	2158
query76	2303	1159	837	837
query77	339	372	271	271
query78	12374	12370	11904	11904
query79	1267	1203	770	770
query80	587	497	390	390
query81	444	277	241	241
query82	574	150	129	129
query83	363	270	251	251
query84	266	150	116	116
query85	859	512	411	411
query86	360	302	277	277
query87	1893	1823	1773	1773
query88	3722	2823	2783	2783
query89	427	389	331	331
query90	1893	179	181	179
query91	169	164	130	130
query92	63	57	58	57
query93	1525	1516	869	869
query94	508	352	292	292
query95	689	469	361	361
query96	1043	839	327	327
query97	2712	2706	2552	2552
query98	212	208	201	201
query99	1167	1134	1035	1035
Total cold run time: 255877 ms
Total hot run time: 170761 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.09	0.05	0.05
query3	0.25	0.14	0.13
query4	1.61	0.14	0.13
query5	0.24	0.23	0.21
query6	1.20	1.14	1.02
query7	0.04	0.01	0.01
query8	0.06	0.04	0.04
query9	0.37	0.32	0.33
query10	0.56	0.57	0.53
query11	0.19	0.14	0.15
query12	0.19	0.15	0.15
query13	0.46	0.47	0.49
query14	1.01	0.99	1.01
query15	0.61	0.60	0.59
query16	0.32	0.32	0.32
query17	1.08	1.11	1.10
query18	0.23	0.22	0.21
query19	1.98	2.03	1.96
query20	0.01	0.01	0.01
query21	15.41	0.21	0.14
query22	4.82	0.05	0.04
query23	16.13	0.31	0.12
query24	2.95	0.43	0.32
query25	0.11	0.05	0.05
query26	0.73	0.20	0.16
query27	0.04	0.04	0.04
query28	3.55	0.92	0.54
query29	12.47	4.34	3.47
query30	0.27	0.15	0.16
query31	2.77	0.58	0.31
query32	3.22	0.58	0.49
query33	3.16	3.20	3.20
query34	15.68	4.20	3.53
query35	3.54	3.51	3.53
query36	0.53	0.44	0.40
query37	0.09	0.06	0.07
query38	0.05	0.04	0.04
query39	0.04	0.02	0.03
query40	0.18	0.16	0.15
query41	0.09	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.03	0.04
Total cold run time: 96.42 s
Total hot run time: 25.22 s

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