Skip to content

[refactor](storage) extract MowKeyProbe and HistoricalRowFetcher - #66151

Open
csun5285 wants to merge 1 commit into
apache:masterfrom
csun5285:refactor/mow-key-probe
Open

[refactor](storage) extract MowKeyProbe and HistoricalRowFetcher #66151
csun5285 wants to merge 1 commit into
apache:masterfrom
csun5285:refactor/mow-key-probe

Conversation

@csun5285

Copy link
Copy Markdown
Contributor
  • MowKeyProbe — one probe behind a Policy: which rows to mark in the delete bitmap, whether a delete-signed row or a row that loses on sequence still needs its old values read, and flexible partial update's insert-after-delete rule.
    Those are exactly the rules the three copies differed by.
  • HistoricalRowFetcher — owns the rowset pins and the read plans used to read those old values.

Both segment writers and the row binlog retriever now delegate to them,RowKeyEncoder gains a second constructor for the probe side, since the key the primary key index is probed with is always the schema key columns while the
writer's encoder builds whatever the segment sorn wrapper, deleted when the partial-update fills move into the transform chain in he follow-ups.

Issue Number: close #xxx

Related PR: #xxx

Problem Summary:

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?

@csun5285

Copy link
Copy Markdown
Contributor Author

/review

@github-actions

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: Your access token could not be refreshed because your refresh token was revoked. Please log out and sign in again.
Workflow run: https://github.com/apache/doris/actions/runs/30336662997

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

@csun5285

Copy link
Copy Markdown
Contributor Author

/review

@csun5285

Copy link
Copy Markdown
Contributor Author

run buildall

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

Automated review opinion: request changes.

The production refactor is coherent and the extracted policy/fetcher behavior matches the removed fixed, flexible, and row-binlog paths. One important proof gap remains: the only test of the new probe-side RowKeyEncoder constructor explicitly excludes cluster-key schemas, even though selecting the primary-key view instead of the cluster sort view is the overload's distinguishing contract. The inline comment requests that coverage.

Critical checkpoint conclusions:

  • Goal and proof: The PR cleanly centralizes MoW lookup policy, historical-row reads, and probe-side key encoding. Static end-to-end tracing supports behavioral equivalence, but the cluster-key probe/index byte contract is not yet directly tested.
  • Scope and clarity: The production changes are focused on the stated extraction; the larger diff is primarily targeted BE unit coverage.
  • Concurrency: No new threads or lock ordering are introduced. Existing writer serialization and delete-bitmap synchronization assumptions are unchanged.
  • Lifecycle and memory: Fixed-path rowsets remain pinned through their block-local historical read; the flexible path keeps its existing writer-owned pins; row binlog retains one fetcher through AFTER and BEFORE generation and clears it between blocks. No ownership cycle or stale-plan path was found.
  • Configuration and observability: No configuration, logging, metric, or dynamic-update contract changes are introduced.
  • Compatibility: No FE/BE protocol, persisted metadata, or storage-format change is introduced. Primary-key, nullable-marker, sequence-suffix, row-id, and row-cache key layouts were traced as unchanged.
  • Parallel paths and conditions: SegmentWriter fixed partial update, VerticalSegmentWriter fixed/flexible partial update, sequence win/lose/equal, delete-sign, insert-after-delete, READ_ONLY/OLD_ROW/OLD_AND_NEW_ROW, row-cache, and row-binlog BEFORE/AFTER paths were checked. TEMP-version old/new-row marks and counters remain aligned with the former code.
  • Transactions and data correctness: Visible-version lookup and TEMP_VERSION_COMMON delete-bitmap behavior are preserved; no new persistence or failover path is added.
  • Performance: The extraction adds no material hot-loop algorithmic regression or redundant I/O.
  • Tests: The added component tests cover the main probe, fetch, cache, sequence, delete, BEFORE/AFTER, and clear/reuse branches. The cluster-key probe-view case called out inline is still required. This review was intentionally read-only and did not run local builds or tests.
  • User focus: No additional review focus was supplied; the complete PR was reviewed.

Comment thread be/test/storage/key/row_key_encoder_test.cpp
@csun5285
csun5285 force-pushed the refactor/mow-key-probe branch from d5d0148 to c3a0734 Compare July 28, 2026 10:48
@csun5285

Copy link
Copy Markdown
Contributor Author

/review

@csun5285

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 64.92% (161/248) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 58.20% (24691/42421)
Line Coverage 42.25% (246730/583928)
Region Coverage 38.17% (196188/513980)
Branch Coverage 39.30% (88596/225451)

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

Automated review opinion: no additional changes requested from code review.

I found no new correctness issue at current head c3a07347983be225868fdbeeb473632154330630. The previous inline request for a cluster-key probe-encoder proof is represented in the current head by ProbeEncoderMatchesPrimaryKeyViewWithClusterKeys, which directly compares the probe-side encoding with the writer's primary-key-index view.

Critical checkpoint conclusions:

  • Goal and proof: The PR cleanly centralizes MoW lookup policy and historical-row ownership while preserving writer and row-binlog behavior. The added unit tests cover encoder views, probe results and bitmap modes, historical reads/defaults, cache invalidation, row-binlog BEFORE/AFTER behavior, sequence loss, and per-block clear.
  • Scope and clarity: The production change is focused on the stated extraction. The unused flexible-fetcher and previous-sequence helpers are preparatory surface but do not change a current runtime path.
  • Concurrency: No new thread entry or lock ordering is introduced. Writer execution remains staged, and delete-bitmap access retains its existing synchronization.
  • Lifecycle and memory: Fixed writer fetchers pin rowsets through their synchronous reads; the flexible path retains the writer-owned pin map needed by its aggregator/read plan; row binlog retains one fetcher through AFTER and BEFORE construction and resets it between blocks. No ownership cycle or stale-plan path was found.
  • Compatibility: No wire, persisted metadata, or storage-format change is introduced. Primary-key prefixes, nullable markers, sequence suffixes, cluster-key rowid suffixes, supported sequence schema evolution, and seqless row-cache keys remain compatible with lookup/index behavior.
  • Parallel paths and conditions: Horizontal fixed, vertical fixed/flexible, read-only row binlog, sequence win/equal/loss, delete-sign, and same-load insert-after-delete paths were checked. TEMP-version old/new-row marks, counters, error propagation, and old-value decisions match the pre-refactor branches.
  • Transactions and data correctness: Visible-version lookup and TEMP_VERSION_COMMON delete-bitmap semantics are preserved; no new persistence, EditLog, or failover path is added.
  • Configuration and observability: No configuration, metric, or logging contract changes are introduced, and no new observability requirement was identified.
  • Performance: The refactor adds no new lookup, historical I/O, cache operation, material allocation, or algorithmic scan in the hot loops.
  • Tests and validation: The current head has passing compile, Linux BE UT, macOS BE UT, formatter, and style checks. This review was intentionally static because the review bundle forbids local builds. At review time, External Regression and BE coverage are failed, while several regression and performance checks remain pending, so CI is not fully green and those checks still need to be resolved independently.
  • User focus: No additional review focus was supplied; the complete PR was reviewed.

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17775	4146	4078	4078
q2	2027	337	202	202
q3	10261	1442	837	837
q4	4688	476	340	340
q5	7518	873	578	578
q6	190	177	143	143
q7	781	834	607	607
q8	9335	1541	1557	1541
q9	5645	4397	4362	4362
q10	6794	1741	1453	1453
q11	511	355	326	326
q12	769	579	451	451
q13	18074	3344	2750	2750
q14	269	264	237	237
q15	q16	791	775	709	709
q17	887	973	900	900
q18	7117	5776	5601	5601
q19	1320	1293	1106	1106
q20	787	671	596	596
q21	6022	2614	2326	2326
q22	421	351	298	298
Total cold run time: 101982 ms
Total hot run time: 29441 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4450	4398	4394	4394
q2	291	312	221	221
q3	4534	5025	4361	4361
q4	2080	2164	1387	1387
q5	4417	4372	4294	4294
q6	233	171	126	126
q7	1711	1993	1863	1863
q8	2597	2227	2226	2226
q9	8110	8167	7872	7872
q10	4671	4644	4238	4238
q11	587	412	418	412
q12	783	764	550	550
q13	3245	3601	2916	2916
q14	294	317	264	264
q15	q16	714	743	667	667
q17	1360	1326	1315	1315
q18	8024	7314	7237	7237
q19	1162	1120	1103	1103
q20	2214	2190	1930	1930
q21	5262	4582	4422	4422
q22	536	447	409	409
Total cold run time: 57275 ms
Total hot run time: 52207 ms

@hello-stephen

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

query5	4323	613	472	472
query6	470	231	211	211
query7	4896	577	335	335
query8	343	184	169	169
query9	8794	4015	4008	4008
query10	485	355	290	290
query11	5892	2306	2092	2092
query12	157	104	102	102
query13	1271	590	444	444
query14	6265	5194	4879	4879
query14_1	4213	4232	4224	4224
query15	218	212	182	182
query16	1022	481	482	481
query17	1146	740	589	589
query18	2716	497	354	354
query19	219	194	157	157
query20	117	107	105	105
query21	244	164	139	139
query22	13512	13448	13406	13406
query23	17476	16609	16160	16160
query23_1	16300	16201	16190	16190
query24	7505	1780	1285	1285
query24_1	1330	1279	1307	1279
query25	589	477	398	398
query26	1346	362	216	216
query27	2500	582	389	389
query28	4384	1963	1990	1963
query29	1083	667	488	488
query30	340	281	237	237
query31	1136	1149	984	984
query32	115	64	62	62
query33	522	330	274	274
query34	1179	1126	648	648
query35	768	776	676	676
query36	1022	1028	885	885
query37	154	107	95	95
query38	1957	1712	1600	1600
query39	883	885	832	832
query39_1	827	820	843	820
query40	243	160	144	144
query41	68	63	62	62
query42	92	91	90	90
query43	317	322	279	279
query44	1441	773	759	759
query45	192	180	170	170
query46	1100	1209	762	762
query47	2148	2085	2025	2025
query48	396	408	293	293
query49	588	426	306	306
query50	1056	414	340	340
query51	10679	10481	10685	10481
query52	87	86	78	78
query53	265	283	203	203
query54	284	244	211	211
query55	74	71	67	67
query56	301	287	282	282
query57	1304	1295	1225	1225
query58	293	251	236	236
query59	1554	1657	1421	1421
query60	308	288	261	261
query61	154	151	152	151
query62	547	493	434	434
query63	238	197	200	197
query64	2807	1086	856	856
query65	4751	4633	4601	4601
query66	1767	497	379	379
query67	29309	29205	28445	28445
query68	3133	1535	961	961
query69	414	301	275	275
query70	912	783	786	783
query71	374	315	320	315
query72	3038	2711	2399	2399
query73	839	764	422	422
query74	5082	4907	4737	4737
query75	2538	2504	2127	2127
query76	2314	1153	775	775
query77	349	376	287	287
query78	11986	11850	11349	11349
query79	1378	1127	712	712
query80	1300	585	456	456
query81	560	341	289	289
query82	844	152	119	119
query83	359	322	292	292
query84	282	160	132	132
query85	980	606	525	525
query86	434	235	235	235
query87	1832	1811	1762	1762
query88	3721	2793	2747	2747
query89	433	375	331	331
query90	1980	197	192	192
query91	198	191	159	159
query92	61	61	54	54
query93	1767	1464	950	950
query94	742	360	305	305
query95	779	568	459	459
query96	1051	853	359	359
query97	2631	2596	2496	2496
query98	214	213	207	207
query99	1081	1112	996	996
Total cold run time: 263921 ms
Total hot run time: 177001 ms

@hello-stephen

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

query1	0.00	0.00	0.01
query2	0.10	0.05	0.05
query3	0.26	0.14	0.14
query4	1.62	0.15	0.13
query5	0.23	0.21	0.23
query6	1.25	1.11	1.07
query7	0.04	0.01	0.00
query8	0.05	0.04	0.04
query9	0.38	0.31	0.30
query10	0.54	0.55	0.54
query11	0.20	0.14	0.13
query12	0.18	0.14	0.14
query13	0.46	0.46	0.48
query14	1.02	1.02	1.02
query15	0.61	0.59	0.60
query16	0.32	0.32	0.33
query17	1.08	1.14	1.10
query18	0.22	0.21	0.21
query19	2.08	1.95	1.94
query20	0.02	0.01	0.01
query21	15.42	0.23	0.13
query22	4.88	0.05	0.05
query23	16.16	0.30	0.13
query24	2.95	0.41	0.34
query25	0.14	0.05	0.06
query26	0.73	0.20	0.16
query27	0.05	0.03	0.04
query28	3.52	0.89	0.53
query29	12.47	4.17	3.34
query30	0.28	0.15	0.16
query31	2.77	0.60	0.32
query32	3.22	0.59	0.48
query33	3.12	3.28	3.26
query34	15.53	4.26	3.51
query35	3.56	3.55	3.50
query36	0.55	0.42	0.42
query37	0.09	0.06	0.06
query38	0.05	0.04	0.03
query39	0.04	0.03	0.03
query40	0.19	0.16	0.15
query41	0.09	0.03	0.04
query42	0.04	0.02	0.02
query43	0.04	0.03	0.04
Total cold run time: 96.55 s
Total hot run time: 25.15 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 83.00% (205/247) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.41% (31195/41367)
Line Coverage 59.90% (347505/580096)
Region Coverage 56.63% (292096/515770)
Branch Coverage 57.92% (130623/225519)

@csun5285
csun5285 force-pushed the refactor/mow-key-probe branch 2 times, most recently from 44c32f8 to 5a38487 Compare July 29, 2026 03:50
@csun5285

Copy link
Copy Markdown
Contributor Author

/review

@csun5285

Copy link
Copy Markdown
Contributor Author

run buildall

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

Automated review opinion: request changes.

The production refactor is focused and the extracted probe policies, delete-bitmap behavior, key encoding, and rowset/read-plan ownership match the removed horizontal, vertical, flexible, and row-binlog paths. One test remains non-discriminating for the central lifecycle contract: ClearResetsThePerBlockState still passes if the old fixed read plan survives clear(). The inline comment requests a shape that actually detects stale state and covers the production consumer order.

Critical checkpoint conclusions:

  • Goal and proof: The PR centralizes MoW key probing and historical-row ownership without changing the intended write behavior. Static tracing supports the production refactor, but the new clear/reuse test does not prove that the old per-block read plan is discarded.
  • Scope and clarity: The production changes are focused on the stated extraction and share the same abstractions across the parallel writers and row-binlog retriever. Most of the larger diff is targeted BE unit coverage.
  • Concurrency: No new thread entry, shared concurrent state, lock order, or atomic protocol is introduced. Writer/retriever state remains stage-local, and existing tablet-header/delete-bitmap synchronization is unchanged.
  • Lifecycle and memory: Fixed writers keep a local fetcher and its rowset pins through the synchronous historical read; the flexible path retains its existing writer-owned pins; row binlog retains one fetcher through AFTER and BEFORE construction and recreates it at block clear. No ownership cycle or unsafe borrowed lifetime was found. The inline finding is specifically that the test would not catch a regression in that final reset step.
  • Configuration and compatibility: No configuration, dynamic-update contract, FE/BE variable, wire protocol, persisted metadata, EditLog, or storage-format change is introduced. Primary-key markers, sequence and cluster-rowid suffixes, row-cache keys, and supported sequence-schema evolution remain compatible.
  • Parallel paths and conditions: Horizontal fixed, vertical fixed/flexible, row-binlog read-only lookup, sequence win/equal/loss, delete-sign handling, same-load insert-after-delete, default/null filling, and cloud-mode guards were checked. TEMP-version bitmap marks, counters, callbacks, and checked error propagation match the former branches.
  • Transactions and data correctness: Visible-version lookup, rowset pinning, and TEMP_VERSION_COMMON delete-bitmap ownership are preserved; no new transaction, failover, or persistence path is added.
  • Error handling, memory safety, and nullable handling: Returned statuses remain checked, unexpected lookup errors propagate, rowset ownership covers deferred reads, and BEFORE nullable insertion retains the established checked shape. No new speculative defensive continuation was added.
  • Performance and observability: The extraction adds no material algorithmic scan, historical I/O, cache operation, lock-held work, or hot-loop allocation. Existing logging is sufficient for this internal refactor; no new metric is required.
  • Tests and results: The added BE unit suites cover encoder views, probe policies, cache invalidation, historical fetches, sequence/delete behavior, BEFORE/AFTER construction, and reuse flags. The accepted inline issue is the remaining false-negative lifecycle test and missing production AFTER -> BEFORE -> clear sequence. No generated regression result is involved. Per the review-only instructions, I did not run local builds or tests.
  • Other issues: A suspected cluster-key equal-prefix lookup problem was dismissed after tracing every supported segment producer: normal MemTable flush, schema change, compaction, and conflict rewrite all deduplicate or filter unique-key rows before persistence. It is not submitted as a speculative blocker.
  • User focus: No additional review focus was supplied; the complete PR was reviewed.

}
retriever.clear();

Block second = key_block(schema, {2});

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.

[P2] Make the clear test fail on a retained read plan

Both batches use the same rowset/segment and plan destination position 0. If clear() stopped recreating _row_fetcher, FixedReadPlan::read_columns_by_plan would read both row-ids and the later mapping would overwrite read_index[0], so this test would still return 22 and pass with stale per-block state. Please make the post-clear batch a miss and assert its BEFORE value is NULL (or otherwise choose a shape where the retained mapping is observable), and cover the production AFTER -> BEFORE -> clear order so the plan is proven to survive both consumers and then be discarded.

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17718	4437	4126	4126
q2	2021	337	205	205
q3	10282	1463	829	829
q4	4680	468	338	338
q5	7528	854	574	574
q6	184	172	135	135
q7	754	816	607	607
q8	9360	1687	1604	1604
q9	5652	4443	4349	4349
q10	6769	1779	1466	1466
q11	508	356	328	328
q12	706	584	467	467
q13	18087	3451	2750	2750
q14	264	270	252	252
q15	q16	804	782	707	707
q17	934	1011	994	994
q18	7336	5729	5568	5568
q19	1336	1244	1008	1008
q20	782	683	565	565
q21	5980	2597	2523	2523
q22	442	364	298	298
Total cold run time: 102127 ms
Total hot run time: 29693 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4442	4380	4388	4380
q2	290	317	218	218
q3	4605	4946	4449	4449
q4	2053	2148	1371	1371
q5	4382	4266	4287	4266
q6	234	178	130	130
q7	1745	2196	1716	1716
q8	2573	2207	2131	2131
q9	7965	7923	7873	7873
q10	4697	4655	4198	4198
q11	556	420	397	397
q12	754	779	543	543
q13	3375	3557	2964	2964
q14	293	313	279	279
q15	q16	716	725	641	641
q17	1367	1328	1327	1327
q18	7866	7231	7295	7231
q19	1167	1135	1074	1074
q20	2207	2204	1942	1942
q21	5211	4550	4476	4476
q22	522	448	397	397
Total cold run time: 57020 ms
Total hot run time: 52003 ms

@hello-stephen

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

query5	4351	628	480	480
query6	470	229	207	207
query7	4853	610	337	337
query8	350	190	172	172
query9	8777	4044	4044	4044
query10	516	393	306	306
query11	5931	2314	2116	2116
query12	156	104	102	102
query13	1267	588	432	432
query14	6242	5258	4869	4869
query14_1	4234	4219	4260	4219
query15	217	198	175	175
query16	1017	477	432	432
query17	1023	745	541	541
query18	2429	463	329	329
query19	210	183	158	158
query20	114	110	103	103
query21	234	155	134	134
query22	13651	13571	13309	13309
query23	17401	16509	16049	16049
query23_1	16211	16246	16238	16238
query24	7587	1741	1240	1240
query24_1	1315	1258	1283	1258
query25	534	434	382	382
query26	1321	376	206	206
query27	2613	562	353	353
query28	4451	2029	1959	1959
query29	1061	604	462	462
query30	333	261	226	226
query31	1113	1083	975	975
query32	121	59	64	59
query33	518	317	239	239
query34	1149	1135	658	658
query35	772	776	661	661
query36	1047	1028	870	870
query37	155	96	85	85
query38	1863	1708	1651	1651
query39	880	877	847	847
query39_1	829	845	843	843
query40	242	163	149	149
query41	64	61	62	61
query42	91	88	85	85
query43	316	321	280	280
query44	1404	781	751	751
query45	194	178	167	167
query46	1062	1188	730	730
query47	2144	2188	2117	2117
query48	372	416	296	296
query49	587	424	304	304
query50	1028	458	327	327
query51	11129	11135	11000	11000
query52	88	85	73	73
query53	262	271	204	204
query54	280	228	221	221
query55	73	71	65	65
query56	289	302	306	302
query57	1344	1302	1224	1224
query58	310	283	279	279
query59	1553	1649	1438	1438
query60	323	284	265	265
query61	179	173	177	173
query62	555	503	434	434
query63	249	210	199	199
query64	2860	1026	832	832
query65	4680	4610	4632	4610
query66	1823	495	382	382
query67	29199	29052	28997	28997
query68	3058	1679	1012	1012
query69	432	317	257	257
query70	884	834	834	834
query71	399	338	327	327
query72	3080	2666	2517	2517
query73	865	769	408	408
query74	5062	4885	4741	4741
query75	2556	2502	2124	2124
query76	2324	1196	790	790
query77	360	390	291	291
query78	11878	11771	11262	11262
query79	1355	1132	746	746
query80	670	577	495	495
query81	462	349	294	294
query82	824	159	125	125
query83	421	338	305	305
query84	308	163	139	139
query85	1037	698	509	509
query86	361	247	227	227
query87	1842	1832	1748	1748
query88	3689	2803	2778	2778
query89	443	358	327	327
query90	1961	194	191	191
query91	201	188	166	166
query92	63	59	55	55
query93	1595	1567	983	983
query94	550	334	303	303
query95	771	489	573	489
query96	1042	779	348	348
query97	2650	2647	2557	2557
query98	225	206	210	206
query99	1090	1111	978	978
Total cold run time: 262882 ms
Total hot run time: 177829 ms

@hello-stephen

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

query1	0.01	0.01	0.03
query2	0.10	0.04	0.05
query3	0.25	0.13	0.13
query4	1.61	0.14	0.14
query5	0.24	0.22	0.22
query6	1.26	1.07	1.08
query7	0.04	0.01	0.00
query8	0.05	0.03	0.03
query9	0.39	0.31	0.31
query10	0.53	0.56	0.56
query11	0.19	0.15	0.14
query12	0.18	0.15	0.14
query13	0.46	0.47	0.48
query14	1.01	1.01	1.01
query15	0.61	0.60	0.58
query16	0.33	0.31	0.32
query17	1.13	1.10	1.13
query18	0.23	0.21	0.20
query19	2.01	1.91	1.93
query20	0.02	0.01	0.01
query21	15.43	0.22	0.13
query22	4.78	0.05	0.05
query23	16.15	0.31	0.12
query24	3.05	0.42	0.34
query25	0.11	0.05	0.06
query26	0.73	0.20	0.16
query27	0.05	0.03	0.03
query28	3.61	0.96	0.53
query29	12.45	4.09	3.29
query30	0.28	0.15	0.15
query31	2.77	0.57	0.31
query32	3.23	0.59	0.48
query33	3.28	3.38	3.19
query34	15.68	4.19	3.50
query35	3.53	3.46	3.53
query36	0.57	0.44	0.42
query37	0.09	0.07	0.06
query38	0.05	0.04	0.04
query39	0.04	0.02	0.02
query40	0.19	0.15	0.15
query41	0.09	0.04	0.03
query42	0.05	0.03	0.03
query43	0.05	0.03	0.04
Total cold run time: 96.91 s
Total hot run time: 24.95 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 86.69% (215/248) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.71% (31868/42092)
Line Coverage 60.32% (354900/588406)
Region Coverage 56.85% (297265/522885)
Branch Coverage 58.29% (133606/229207)

@csun5285
csun5285 force-pushed the refactor/mow-key-probe branch from 5a38487 to 1cbdc56 Compare July 29, 2026 07:43
…ment writers and row-binlog retriever delegate probe, row-cache invalidation and old-value reads

Part 2/6 of splitting apache#64674 (block transform chain) into independently
reviewable PRs. Part 1 was apache#65492 (RowKeyEncoder).

The merge-on-write primary key probe - look the key up in the load's rowset
snapshot, mark the delete bitmap, decide whether the old row has to be read for
the missing columns - existed in three near-verbatim copies:
SegmentWriter::probe_key_for_mow, VerticalSegmentWriter::_probe_key_for_mow and
PrimaryKeyModelRowRetriever. The key encoding around it and the row-cache
invalidation were duplicated the same way. The three copies differ in exactly
three rules, all of which were expressed by copy-editing the code.

Extract them into storage/mow/:

- MowKeyProbe: one probe behind a Policy (delete_bitmap_mode READ_ONLY /
  OLD_ROW / OLD_AND_NEW_ROW, skip_delete_sign, skip_seq_loses,
  skip_in_load_deleted), plus probe_previous_seq_value(),
  maybe_invalidate_row_cache() and encode_mow_key_invalidate_cache(), which
  encodes a key, invalidates the row cache and appends the sequence suffix in
  the one order that is correct.
- HistoricalRowFetcher: owns the rowset pins and the read plans behind
  FixedReadPlan / FlexibleReadPlan.

All three call sites delegate. Both writers keep a thin wrapper that turns a
ProbeOutcome back into the out-parameters their fill loops use and run their
fixed partial-update fill on a per-call HistoricalRowFetcher; the wrappers are
bridge code, deleted when the fills move into chain stages.
PrimaryKeyModelRowRetriever drops its own encode / probe / row-cache copies and
holds a RowKeyEncoder plus a HistoricalRowFetcher, still driven by the existing
RowBinlogSegmentWriter so the row-binlog regressions cover the rework.

RowKeyEncoder gains a second constructor for the probe side: the key the primary
key index is built on is always the schema key columns, while the writer's
constructor builds whatever the segment sorts by (cluster keys when it has them)
plus the separate primary-key view and the rowid suffix. The retriever is the
first caller that has to encode primary keys for any mow table, with or without
cluster keys.

Equivalence notes: the Policy reproduces all three old copies term for term
(delete-bitmap keys, marked rows and stat counters unchanged); SegmentWriter's
cast_set<uint32_t>(max_version) truncation is dropped in favour of the int64
behavior the other two callers already had; lookup_row_key is called with an
explicit with_rowid=false, which fixes the retriever on cluster-key mow tables
(the default strips ROW_ID_LENGTH bytes off a probe key that carries no rowid
suffix) and is inert for partial update, which FE forbids on those tables;
num_rows_new_added is bumped inside probe(), before the writers' handle_new_key
runs at the call site; fixed-path rowset pins move from writer-lifetime maps to
the per-call fetcher, so SegmentWriter::_rsid_to_rowset is gone while the
vertical writer keeps its map for the flexible fill and BlockAggregator; the
retriever's clear() now also drops the fetcher that holds the read plan.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@csun5285
csun5285 force-pushed the refactor/mow-key-probe branch from 1cbdc56 to a084c9d Compare July 29, 2026 08:03
@csun5285

Copy link
Copy Markdown
Contributor Author

/review

@csun5285

Copy link
Copy Markdown
Contributor Author

run buildall

1 similar comment
@csun5285

Copy link
Copy Markdown
Contributor Author

run buildall

@csun5285

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17678	4014	3974	3974
q2	2362	318	199	199
q3	10256	1448	880	880
q4	4687	473	337	337
q5	7702	842	572	572
q6	188	167	138	138
q7	756	806	606	606
q8	9978	1455	1478	1455
q9	7086	4308	4335	4308
q10	7546	1716	1467	1467
q11	659	346	320	320
q12	738	577	454	454
q13	18132	3333	2724	2724
q14	270	260	250	250
q15	q16	787	783	705	705
q17	1043	1009	995	995
q18	6988	5668	5499	5499
q19	1163	1247	1121	1121
q20	812	668	574	574
q21	5768	2592	2489	2489
q22	426	348	297	297
Total cold run time: 105025 ms
Total hot run time: 29364 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4343	4281	4278	4278
q2	289	312	214	214
q3	4556	4935	4385	4385
q4	2053	2141	1375	1375
q5	4358	4250	4284	4250
q6	228	183	148	148
q7	2127	1956	1547	1547
q8	2475	2094	2112	2094
q9	7647	7605	7741	7605
q10	4680	4626	4225	4225
q11	714	409	369	369
q12	755	784	535	535
q13	3252	3570	2939	2939
q14	325	306	271	271
q15	q16	704	724	633	633
q17	1345	1332	1336	1332
q18	7954	7405	6955	6955
q19	1126	1075	1145	1075
q20	2207	2207	1956	1956
q21	5198	4477	4389	4389
q22	520	445	404	404
Total cold run time: 56856 ms
Total hot run time: 50979 ms

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17869	4212	4149	4149
q2	2025	315	199	199
q3	10376	1470	820	820
q4	4681	474	345	345
q5	7515	881	572	572
q6	180	168	135	135
q7	748	800	621	621
q8	9321	1621	1621	1621
q9	5547	4379	4346	4346
q10	6743	1784	1481	1481
q11	523	349	322	322
q12	742	576	469	469
q13	18087	3363	2777	2777
q14	269	256	238	238
q15	q16	793	778	706	706
q17	1055	990	909	909
q18	6982	5732	5569	5569
q19	1205	1317	1142	1142
q20	862	714	604	604
q21	5772	2661	2402	2402
q22	417	351	296	296
Total cold run time: 101712 ms
Total hot run time: 29723 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4412	4404	4365	4365
q2	288	319	215	215
q3	4627	4937	4378	4378
q4	2073	2170	1371	1371
q5	4414	4257	4302	4257
q6	228	176	129	129
q7	1714	2030	1859	1859
q8	2510	2178	2216	2178
q9	8281	8037	7783	7783
q10	4687	4662	4235	4235
q11	585	412	418	412
q12	758	770	531	531
q13	3304	3652	2965	2965
q14	306	299	272	272
q15	q16	710	730	637	637
q17	1346	1319	1317	1317
q18	7844	7228	7409	7228
q19	1164	1133	1119	1119
q20	2204	2196	1925	1925
q21	5254	4543	4446	4446
q22	528	459	402	402
Total cold run time: 57237 ms
Total hot run time: 52024 ms

@hello-stephen

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

query5	4322	653	482	482
query6	478	224	219	219
query7	5026	606	339	339
query8	337	195	174	174
query9	8767	4059	4072	4059
query10	493	353	282	282
query11	5943	2316	2125	2125
query12	163	107	104	104
query13	1277	559	436	436
query14	6207	5159	4872	4872
query14_1	4234	4258	4242	4242
query15	209	201	183	183
query16	1028	483	502	483
query17	957	726	583	583
query18	2452	556	353	353
query19	216	197	152	152
query20	108	110	107	107
query21	233	164	140	140
query22	13530	13569	13337	13337
query23	17320	16471	16165	16165
query23_1	16225	16297	16176	16176
query24	7562	1761	1306	1306
query24_1	1319	1324	1295	1295
query25	566	450	386	386
query26	1341	366	214	214
query27	2595	570	381	381
query28	4506	2042	2053	2042
query29	1083	626	504	504
query30	350	266	232	232
query31	1123	1095	989	989
query32	135	64	61	61
query33	528	331	269	269
query34	1169	1150	653	653
query35	769	786	660	660
query36	1034	1005	942	942
query37	156	101	88	88
query38	1849	1705	1629	1629
query39	867	870	838	838
query39_1	824	833	836	833
query40	257	169	139	139
query41	64	64	62	62
query42	92	95	92	92
query43	321	327	280	280
query44	1424	785	758	758
query45	196	181	164	164
query46	1104	1179	733	733
query47	2124	2114	2033	2033
query48	404	411	297	297
query49	575	407	303	303
query50	1000	441	338	338
query51	10959	10694	10552	10552
query52	86	87	74	74
query53	261	278	201	201
query54	286	241	224	224
query55	74	71	67	67
query56	296	308	279	279
query57	1323	1309	1206	1206
query58	283	254	256	254
query59	1558	1588	1420	1420
query60	319	272	251	251
query61	177	168	147	147
query62	549	494	436	436
query63	242	199	205	199
query64	2810	1082	831	831
query65	4692	4657	4626	4626
query66	1844	560	411	411
query67	29287	29359	29037	29037
query68	3058	1554	1055	1055
query69	405	295	270	270
query70	928	799	794	794
query71	361	334	326	326
query72	3137	2668	2356	2356
query73	857	834	419	419
query74	5074	4890	4733	4733
query75	2545	2504	2116	2116
query76	2294	1147	759	759
query77	351	384	281	281
query78	11966	11898	11309	11309
query79	1389	1135	731	731
query80	1280	577	488	488
query81	562	333	290	290
query82	971	155	118	118
query83	381	327	304	304
query84	324	160	126	126
query85	1024	629	525	525
query86	424	239	236	236
query87	1847	1823	1738	1738
query88	3737	2806	2775	2775
query89	445	375	324	324
query90	1923	193	199	193
query91	202	190	166	166
query92	64	63	58	58
query93	1664	1702	978	978
query94	737	346	334	334
query95	785	508	485	485
query96	1087	792	364	364
query97	2628	2629	2525	2525
query98	217	212	206	206
query99	1096	1118	973	973
Total cold run time: 264102 ms
Total hot run time: 177455 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 a084c9d5068d399e6569d3b013d923ee368202a7, data reload: false

query1	0.00	0.00	0.00
query2	0.10	0.04	0.05
query3	0.26	0.14	0.13
query4	1.62	0.14	0.13
query5	0.24	0.23	0.22
query6	1.27	1.10	1.10
query7	0.03	0.01	0.01
query8	0.06	0.04	0.03
query9	0.44	0.31	0.34
query10	0.54	0.56	0.59
query11	0.21	0.13	0.14
query12	0.18	0.14	0.14
query13	0.46	0.48	0.48
query14	1.05	1.01	1.02
query15	0.61	0.60	0.59
query16	0.31	0.33	0.31
query17	1.15	1.12	1.08
query18	0.23	0.22	0.21
query19	1.99	1.93	1.96
query20	0.02	0.01	0.01
query21	15.51	0.22	0.13
query22	4.71	0.05	0.05
query23	16.14	0.31	0.12
query24	3.04	0.43	0.36
query25	0.12	0.05	0.04
query26	0.74	0.22	0.14
query27	0.04	0.05	0.03
query28	3.49	0.92	0.53
query29	12.52	4.10	3.28
query30	0.28	0.16	0.16
query31	2.78	0.59	0.31
query32	3.23	0.60	0.48
query33	3.11	3.20	3.27
query34	15.54	4.19	3.58
query35	3.52	3.54	3.54
query36	0.56	0.43	0.43
query37	0.08	0.06	0.07
query38	0.05	0.04	0.03
query39	0.04	0.03	0.03
query40	0.18	0.17	0.16
query41	0.08	0.03	0.03
query42	0.04	0.03	0.03
query43	0.05	0.04	0.03
Total cold run time: 96.62 s
Total hot run time: 25.17 s

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

Automated review opinion: no additional changes requested.

At reviewed head a084c9d5068d399e6569d3b013d923ee368202a7, I found no new
correctness issue. Both earlier inline proof gaps are addressed in the current code: the
cluster-key primary-key view is separated from the segment sort-key view with byte-level
primary/sequence/rowid coverage, and the clear test now exercises AFTER -> BEFORE -> clear before a
miss whose BEFORE value must remain NULL.

Critical checkpoint conclusions:

  • Goal and proof: The PR consistently centralizes MoW key probing, primary-key encoding/cache
    invalidation, and historical-row ownership. Component tests exercise real primary indexes and
    the key policy/fetch/retriever contracts.
  • Scope and clarity: The production changes are focused on the extraction. The preparatory
    previous-sequence and flexible-fetcher surfaces are not production-wired yet, but introduce no
    current behavior change.
  • Concurrency: No new thread entry, shared concurrent state, lock order, or atomic protocol is
    introduced. The affected writer/retriever stages remain sequential.
  • Lifecycle and memory: Fixed paths pin rowsets through their synchronous historical reads;
    vertical flexible keeps its existing writer-owned pins; row binlog preserves one plan through
    AFTER and BEFORE and discards it at per-block clear. No ownership cycle or premature release was
    found.
  • Configuration and observability: No configuration or dynamic-update contract changes. Lookup
    failures retain checked propagation and now include tablet/transaction context; no new metric is
    required for this refactor.
  • Compatibility: No FE/BE protocol, persisted metadata, or storage-format change. Primary-key
    markers, nullable markers, sequence suffixes, cluster rowid suffixes, and sequence-less row-cache
    keys remain aligned with primary-index construction and lookup.
  • Parallel paths and conditions: Horizontal fixed, vertical fixed/flexible, and row-binlog paths
    were checked across misses, sequence win/equal/loss, delete signs, same-load insert-after-delete,
    row-store/column-store reads, and BEFORE/AFTER generation. The policy outcomes match the removed
    branches.
  • Transactions and data correctness: Visible-version lookup and immediate
    TEMP_VERSION_COMMON old/incoming-row marks, targets, and counters are preserved. Failures still
    abort through checked statuses; no new commit, persistence, or failover path is added.
  • Performance: No additional lookup, historical I/O, asymptotic scan, lock-held work, or material
    hot-loop allocation was introduced.
  • Tests and validation: The changed unit tests cover encoder views and suffixes, probe policies,
    cache invalidation, historical reads/defaults, delete/sequence behavior, BEFORE/AFTER reuse, and
    clear. No generated regression result is involved. Per the review-runner contract, this review
    was static and did not run local builds or tests; repository CI remains an independent merge
    gate.
  • User focus: No additional review focus was supplied; the complete PR was reviewed.

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

Automated review opinion: no additional changes requested.

At reviewed head a084c9d5068d399e6569d3b013d923ee368202a7, no new correctness issue survived the full review and convergence pass. The two earlier inline proof concerns are covered by the current code:

  • Cluster-key encoding: AllKeyTypesTable independently compares the cluster-key primary view with canonical primary-key bytes across all key types, includes cluster-plus-sequence primary-index entries, and snapshots exact bytes. RowidSuffix separately checks exact primary + sequence + rowid bytes. The narrower focused test is not the sole proof.
  • Retriever lifecycle: ClearResetsThePerBlockState now follows the production AFTER -> BEFORE -> clear order, then probes a miss and requires its BEFORE value to remain NULL, so both premature plan consumption and stale-plan retention are observable.

Critical checkpoint conclusions:

  • Goal and proof: The PR consistently centralizes MoW key probing, cache invalidation, and historical-row ownership while preserving the removed horizontal, vertical, flexible, and row-binlog behavior. The helper and retriever tests exercise real primary-index lookup and the policy/read-plan contracts.
  • Scope and clarity: The production changes are focused on the stated extraction. Preparatory previous-sequence and flexible-fetcher APIs are not production-wired yet but do not alter a current runtime path.
  • Concurrency: No new thread entry, lock order, atomic protocol, or independently shared mutable state is introduced. The affected writer/retriever stages remain sequential, and existing delete-bitmap synchronization assumptions are unchanged.
  • Lifecycle and memory: Fixed writers keep each read plan and its RowsetSharedPtr pins through the synchronous fill. Vertical flexible retains the writer-owned map used by its aggregator/read plan. Row binlog keeps one fetcher through AFTER and BEFORE, then recreates it at per-block clear. No ownership cycle, premature release, or stale-plan path remains.
  • Configuration and compatibility: No configuration, dynamic-update contract, FE/BE variable, wire protocol, persisted metadata, EditLog, or storage-format change is introduced. Primary-key markers, nullable markers, sequence suffixes, cluster rowid suffixes, and sequence-less row-cache keys remain aligned with primary-index construction and lookup.
  • Parallel paths and special conditions: Horizontal fixed, vertical fixed/flexible, and read-only row-binlog paths were checked for misses, sequence win/equal/loss, delete signs, same-load insert-after-delete, row-store/column-store reads, and BEFORE/AFTER generation. Policy outcomes and handle_new_key behavior match the former branches.
  • Transactions and data correctness: Visible-version lookup and immediate TEMP_VERSION_COMMON marks preserve their targets, timing, and counters. Returned lookup/read errors remain checked and abort the write; no new commit, persistence, failover, or silent-continuation path is added.
  • Test coverage and results: The changed BE unit tests cover encoder views/suffixes, probe policies, cache invalidation, historical reads/defaults, delete/sequence behavior, BEFORE/AFTER reuse, and clear. No generated regression result is involved. Per the review-runner contract, this review was static and did not run local builds or tests. Repository CI is still an independent merge gate.
  • Observability: Lookup failures now retain tablet/transaction context, and no new long-lived or distributed operation needs a metric or additional logging.
  • Performance: The refactor adds no extra lookup, historical I/O, asymptotic scan, lock-held work, or material hot-loop allocation.
  • Other concerns: No additional correctness, nullable-shape, memory-tracking, or compatibility issue was substantiated.
  • User focus: No additional review focus was supplied; the complete PR was reviewed.

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 86.18% (212/246) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.74% (31983/42228)
Line Coverage 60.40% (356503/590221)
Region Coverage 57.01% (299154/524753)
Branch Coverage 58.34% (134488/230543)

1 similar comment
@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 86.18% (212/246) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.74% (31983/42228)
Line Coverage 60.40% (356503/590221)
Region Coverage 57.01% (299154/524753)
Branch Coverage 58.34% (134488/230543)

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