Skip to content

[opt](bucket pruning) Avoid materializing tablet IDs during pruning - #67150

Open
zyp-V wants to merge 1 commit into
apache:masterfrom
zyp-V:compute_tablet
Open

[opt](bucket pruning) Avoid materializing tablet IDs during pruning#67150
zyp-V wants to merge 1 commit into
apache:masterfrom
zyp-V:compute_tablet

Conversation

@zyp-V

@zyp-V zyp-V commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary: Hash tablet pruning eagerly materialized every tablet ID before evaluating selective predicates. Backport the MaterializedIndex-backed pruning path so tablet IDs are resolved by bucket only when needed, while preserving the current branch's materialized-view column mapping. Migrate the remaining unit tests to the index-backed API and remove the obsolete list-backed constructor.

Release note

None

Check List (For Author)

  • Test: No test run (per explicit request to skip compilation and directly review the code)

  • Behavior changed: No

  • Does this need documentation: No

What problem does this PR solve?

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?

@HonestManXin

Copy link
Copy Markdown
Contributor

/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 conclusion: request changes

The production optimization is otherwise sound: it preserves bucket ordering and planner-path behavior, and selective HASH pruning avoids the eager O(N) boxed-ID list. One blocking test migration remains.

Critical checkpoints:

  • Goal and scope: the focused allocation reduction works, but the PR is not merge-ready because an existing Nereids rewrite test still mocks the old accessor and now fails.
  • Data correctness and parallel paths: selected-tablet membership and order remain equivalent across Nereids, legacy, short-circuit point queries, rollup/MV, row-binlog, manual/sample, HASH/RANDOM, and null/empty/all outcomes.
  • Concurrency and lifecycle: the pruner captures one copy-on-write MaterializedIndex tablet snapshot; normal/cloud creation, restore, Gson reconstruction, and downstream bucket-sequence mapping preserve bucket order. No new lock, deadlock, static-initialization, or ownership issue was found.
  • Compatibility, configuration, persistence, and writes: no configuration, FE-BE/thrift/storage-format, persistence, transaction, data-write, or rolling-upgrade surface is changed.
  • Error handling and observability: no new Status/RPC boundary or runtime instrumentation need is introduced.
  • Performance: selective paths materialize only chosen IDs; fallback paths retain the required ordered O(N) result without the former extra eager ID list.
  • Tests and results: the migrated direct unit fixtures and selected/all-bucket assertions are structurally sound, and CheckStyle passed. No FE unit-test job ran, and RewriteRuleSuiteTest.testPruneOlapScanTablet will fail until its MaterializedIndex mock supplies getTablets().
  • User focus: no additional focus was provided.

Review completion: complete after two rounds; every candidate was verified and deduplicated, with MAIN-001 as the sole accepted issue.

### What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary: Hash tablet pruning eagerly materialized every tablet ID before evaluating selective predicates. Backport the MaterializedIndex-backed pruning path so tablet IDs are resolved by bucket only when needed, while preserving the current branch's materialized-view column mapping. Migrate all affected unit tests, including the Nereids rewrite fixture, to the index-backed API and remove the obsolete list-backed constructor.

### Release note

None

### Check List (For Author)

- Test: Unit Test
    - ./run-fe-ut.sh --run org.apache.doris.planner.HashDistributionPrunerTest,org.apache.doris.planner.OlapScanNodeTest,org.apache.doris.nereids.rules.rewrite.RewriteRuleSuiteTest
- Behavior changed: No
- Does this need documentation: No
@morrySnow

Copy link
Copy Markdown
Contributor

run buildall

@morrySnow morrySnow changed the title [improvement](fe) Avoid materializing tablet IDs during pruning [opt](bucket pruning) Avoid materializing tablet IDs during pruning Aug 26, 2026
@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17554	3046	2995	2995
q2	2095	260	225	225
q3	10225	869	527	527
q4	4673	250	198	198
q5	7678	570	393	393
q6	139	116	98	98
q7	529	506	385	385
q8	9246	937	976	937
q9	3478	2411	2413	2411
q10	6520	859	713	713
q11	396	202	183	183
q12	622	264	195	195
q13	18111	1540	1173	1173
q14	156	150	144	144
q15	q16	432	397	372	372
q17	1344	820	849	820
q18	3031	2274	2244	2244
q19	1120	937	834	834
q20	387	286	200	200
q21	5279	1742	1864	1742
q22	326	269	230	230
Total cold run time: 93341 ms
Total hot run time: 17019 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3395	3344	3327	3327
q2	521	401	381	381
q3	2181	2369	2185	2185
q4	1197	1170	896	896
q5	2168	2113	2113	2113
q6	174	122	87	87
q7	1059	947	943	943
q8	1640	1424	1433	1424
q9	3107	3097	3082	3082
q10	1858	1787	1669	1669
q11	355	273	253	253
q12	448	431	346	346
q13	1486	1554	1150	1150
q14	168	184	162	162
q15	q16	396	406	372	372
q17	3642	3326	3250	3250
q18	4901	4445	4797	4445
q19	3727	888	847	847
q20	980	972	845	845
q21	3771	3046	3208	3046
q22	408	346	324	324
Total cold run time: 37582 ms
Total hot run time: 31147 ms

@hello-stephen

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

query5	4303	410	350	350
query6	403	139	126	126
query7	5026	435	224	224
query8	728	127	115	115
query9	8641	2918	2885	2885
query10	422	237	188	188
query11	5385	1047	923	923
query12	116	74	72	72
query13	1194	422	335	335
query14	6011	2216	2099	2099
query14_1	1970	1958	1943	1943
query15	179	121	114	114
query16	3164	390	357	357
query17	839	451	377	377
query18	2154	335	240	240
query19	216	142	114	114
query20	73	70	70	70
query21	757	101	88	88
query22	5540	5329	5275	5275
query23	6582	6207	6045	6045
query23_1	5980	6198	6084	6084
query24	7257	1118	807	807
query24_1	754	788	757	757
query25	443	315	264	264
query26	1254	252	136	136
query27	2700	399	254	254
query28	4719	1499	1499	1499
query29	941	463	361	361
query30	368	172	126	126
query31	834	430	326	326
query32	123	78	71	71
query33	513	231	180	180
query34	1008	816	502	502
query35	405	516	365	365
query36	581	562	553	553
query37	121	76	68	68
query38	1029	865	852	852
query39	524	522	508	508
query39_1	496	482	480	480
query40	265	88	75	75
query41	55	50	72	50
query42	71	69	71	69
query43	252	254	209	209
query44	1053	543	557	543
query45	113	105	96	96
query46	801	839	549	549
query47	778	754	697	697
query48	308	297	244	244
query49	576	250	182	182
query50	804	283	207	207
query51	8077	8112	7985	7985
query52	63	65	62	62
query53	188	195	155	155
query54	218	165	169	165
query55	79	60	53	53
query56	199	179	146	146
query57	819	633	640	633
query58	198	174	156	156
query59	1210	1154	1035	1035
query60	280	175	172	172
query61	116	119	109	109
query62	366	193	182	182
query63	170	141	131	131
query64	2220	653	535	535
query65	1626	1514	1614	1514
query66	1663	259	206	206
query67	9913	9569	9673	9569
query68	2779	1159	755	755
query69	436	224	195	195
query70	640	623	591	591
query71	247	187	159	159
query72	2678	1749	1636	1636
query73	652	631	338	338
query74	1574	1237	1163	1163
query75	1185	1120	974	974
query76	1852	739	565	565
query77	351	273	217	217
query78	3932	3749	3176	3176
query79	2473	840	591	591
query80	1519	322	294	294
query81	513	159	135	135
query82	635	128	103	103
query83	278	211	196	196
query84	322	118	96	96
query85	837	359	296	296
query86	399	179	175	175
query87	1011	974	884	884
query88	2763	2106	2092	2092
query89	283	194	171	171
query90	1979	122	120	120
query91	134	119	99	99
query92	78	73	64	64
query93	1493	1131	759	759
query94	658	276	211	211
query95	516	324	225	225
query96	869	568	272	272
query97	1043	1037	998	998
query98	163	133	131	131
query99	548	343	305	305
Total cold run time: 186574 ms
Total hot run time: 82008 ms

@hello-stephen

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

query1	0.01	0.01	0.00
query2	0.41	0.04	0.04
query3	0.74	0.11	0.11
query4	2.04	0.10	0.09
query5	0.17	0.17	0.16
query6	1.65	0.70	0.70
query7	0.03	0.00	0.01
query8	0.05	0.02	0.03
query9	0.62	0.21	0.22
query10	0.35	0.35	0.36
query11	0.30	0.11	0.12
query12	0.20	0.12	0.13
query13	0.31	0.30	0.31
query14	0.50	0.45	0.45
query15	0.38	0.34	0.35
query16	0.25	0.26	0.23
query17	0.73	0.68	0.64
query18	0.17	0.17	0.17
query19	1.49	1.21	1.18
query20	0.01	0.01	0.02
query21	16.96	0.15	0.12
query22	4.77	0.05	0.04
query23	17.13	0.25	0.12
query24	17.28	0.33	0.25
query25	0.09	0.05	0.04
query26	0.73	0.16	0.12
query27	0.03	0.03	0.03
query28	3.64	0.58	0.29
query29	12.48	3.25	2.56
query30	0.24	0.12	0.12
query31	2.80	0.38	0.17
query32	3.57	0.32	0.23
query33	1.38	1.40	1.41
query34	15.35	2.23	1.77
query35	1.76	1.73	1.73
query36	0.46	0.30	0.30
query37	0.22	0.04	0.04
query38	0.05	0.03	0.03
query39	0.17	0.03	0.03
query40	0.18	0.09	0.08
query41	0.36	0.03	0.02
query42	0.22	0.02	0.02
query43	0.03	0.02	0.03
Total cold run time: 110.31 s
Total hot run time: 14.76 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 88.00% (22/25) 🎉
Increment coverage report
Complete coverage report

@HonestManXin

Copy link
Copy Markdown
Contributor

/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 conclusion: request changes

One new blocking performance issue remains at the current head: non-point all-bucket scans lose the old boxed-tablet-ID reuse and can retain more allocation on the common full-scan path. The earlier Nereids Mockito failure is fixed at this head, its live thread is resolved, and it is not duplicated here.

Critical checkpoints:

  • Goal and proof: the index-backed pruner achieves the intended O(K) ID materialization for selective point pruning, but MAIN-001 shows that non-point all-bucket planning can retain N extra Long objects, so the optimization is not yet safe across its full scope.
  • Scope and clarity: the six-file internal FE API/test migration is otherwise small and focused; all seven constructor call sites are migrated.
  • Data correctness and parallel paths: bucket order and selected-tablet semantics remain equivalent across Nereids/legacy, HASH/RANDOM, point/non-point, base/rollup, manual/specified/sample, null/empty/all-result, missing-tablet, and bucket-sequence paths.
  • Concurrency and lifecycle: MaterializedIndex.getTablets() supplies a stable copy-on-write bucket-ordered snapshot; creation, shadow/rollup publication, and restore preserve count/order. No new lock, deadlock, static-initialization, ownership, or cleanup issue was found.
  • Configuration, compatibility, persistence, and writes: no configuration, FE-BE/thrift/storage-format, rolling-upgrade, EditLog, transaction, or data-write surface changes.
  • Error handling and observability: no new error boundary is weakened, and no additional runtime logging or metrics are needed for this internal planner allocation change.
  • Performance: selective point paths improve, but MAIN-001 is a concrete retained-allocation regression for non-point all-bucket/HASH/Nereids paths and needs correction or evidence from allocation benchmarks.
  • Tests and results: the current tests cover sparse ordered IDs, selective and all-tablet fallback, Nereids integration, and isolated index fixtures. Current-head compile, FE UT, CheckStyle, and performance checks pass. check_coverage_fe (Coverage) currently fails with TeamCity build failed; no local build or test was run because the review prompt forbids it.
  • User focus: no additional focus was provided.

Review completion: complete after two convergence rounds; every risk and candidate was independently verified, deduplicated, accepted, or dismissed. MAIN-001 is the sole new accepted inline issue.

tabletId2BucketSeq.put(allTabletIds.get(i), i);
List<Tablet> allTablets = selectedTable.getTablets();
for (int i = 0; i < allTablets.size(); i++) {
tabletId2BucketSeq.put(allTablets.get(i).getId(), i);

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] Reuse the boxed tablet IDs when building bucket sequences

Non-point scans still need one ID per tablet as a tabletId2BucketSeq key, but this loop now boxes each ID again after the selected/result path has already boxed it. Previously allTabletIds created N Longs once and both scanTabletIds and this map retained those same objects. On a no-predicate/all-bucket scan, the new code therefore retains two distinct Longs per tablet; production IDs are outside the small Long cache, so removing the N-reference list can actually increase allocation on this common path. Please build the ordered boxed IDs once—or otherwise share each boxed ID between selection and bucket bookkeeping—so the optimization does not regress non-point/full-scan planning memory.

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.

4 participants