Skip to content

[fix](be) Avoid materializing complex columns for external count#65560

Closed
xylaaaaa wants to merge 1 commit into
apache:masterfrom
xylaaaaa:codex/fix-v2-count-complex-memory-pr
Closed

[fix](be) Avoid materializing complex columns for external count#65560
xylaaaaa wants to merge 1 commit into
apache:masterfrom
xylaaaaa:codex/fix-v2-count-complex-memory-pr

Conversation

@xylaaaaa

@xylaaaaa xylaaaaa commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary: COUNT(nullable complex column) over Parquet or ORC file TVFs cannot use COUNT(*) row metadata because top-level NULL values must be excluded. With FileScannerV2, the query therefore decoded the full complex column through Arrow and then materialized Doris columns, retaining decoded binary chunks and causing excessive peak memory or intermittent OOM. This change introduces an explicit COUNT_NON_NULL operation and target slot from FE to BE. Parquet counts top-level shape from bounded definition/repetition-level batches without Arrow builders or Doris value columns, while ORC uses non-null stripe statistics. It also emits valid non-NULL synthetic target rows and releases file-block ownership before mutable output conversion to avoid unnecessary COW copies.

Release note

Reduce memory usage for COUNT on nullable columns read from Parquet and ORC file TVFs with FileScannerV2.

Check List (For Author)

  • Test: Unit Test
    • FE PhysicalStorageLayerAggregateTest: 4 tests passed
    • BE targeted Parquet, ORC, and TableReader tests: 14 tests passed
    • HDFS TVF regression assertion added but not run locally because this worktree has no Doris cluster or external HDFS test environment
  • Behavior changed: Yes. Eligible nullable file-column counts use explicit COUNT_NON_NULL pushdown instead of materializing the full column.
  • Does this need documentation: No

Copilot AI review requested due to automatic review settings July 13, 2026 17:10
@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 was unable to review this pull request because the user who requested the review has reached their quota limit.

@xylaaaaa xylaaaaa force-pushed the codex/fix-v2-count-complex-memory-pr branch from 7a26fef to 994746b Compare July 13, 2026 17:11
@xylaaaaa

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17839	4061	4110	4061
q2	1999	326	199	199
q3	10860	1425	813	813
q4	4806	462	333	333
q5	8436	866	575	575
q6	339	173	138	138
q7	833	844	617	617
q8	10546	1595	1630	1595
q9	5948	4472	4436	4436
q10	6752	1781	1507	1507
q11	503	347	305	305
q12	728	542	440	440
q13	18385	3310	2731	2731
q14	261	269	243	243
q15	q16	792	766	726	726
q17	1003	894	1023	894
q18	6916	5916	5602	5602
q19	1184	1261	1105	1105
q20	746	692	555	555
q21	5518	2482	2459	2459
q22	427	356	292	292
Total cold run time: 104821 ms
Total hot run time: 29626 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4345	4307	4324	4307
q2	289	318	210	210
q3	4571	4963	4375	4375
q4	2045	2120	1343	1343
q5	4438	4296	4330	4296
q6	226	173	156	156
q7	2168	1858	1643	1643
q8	2506	2172	2128	2128
q9	7883	7859	7795	7795
q10	4736	4689	4464	4464
q11	574	414	392	392
q12	786	746	571	571
q13	3242	3600	2977	2977
q14	299	300	298	298
q15	q16	771	716	632	632
q17	1382	1377	1371	1371
q18	8021	7071	6683	6683
q19	1117	1036	1092	1036
q20	2240	2192	1956	1956
q21	5190	4528	4416	4416
q22	507	449	402	402
Total cold run time: 57336 ms
Total hot run time: 51451 ms

@hello-stephen

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

query5	4322	645	484	484
query6	454	209	202	202
query7	4861	548	344	344
query8	338	200	170	170
query9	8788	4027	4035	4027
query10	474	353	322	322
query11	5958	2372	2130	2130
query12	162	103	103	103
query13	1299	589	440	440
query14	6438	5204	4885	4885
query14_1	4263	4230	4290	4230
query15	219	206	179	179
query16	1039	499	430	430
query17	1086	700	558	558
query18	2679	459	346	346
query19	196	179	142	142
query20	111	106	106	106
query21	231	153	128	128
query22	13608	13658	13412	13412
query23	17349	16419	16093	16093
query23_1	16261	16227	16207	16207
query24	7450	1770	1303	1303
query24_1	1319	1312	1307	1307
query25	572	477	407	407
query26	1328	358	218	218
query27	2566	599	386	386
query28	4453	1990	2024	1990
query29	1083	663	496	496
query30	328	264	226	226
query31	1129	1112	975	975
query32	115	65	62	62
query33	511	326	267	267
query34	1171	1109	675	675
query35	785	789	684	684
query36	1406	1409	1236	1236
query37	167	111	96	96
query38	1864	1695	1680	1680
query39	930	910	889	889
query39_1	886	895	873	873
query40	259	163	145	145
query41	71	68	69	68
query42	97	96	94	94
query43	318	325	274	274
query44	1395	801	791	791
query45	208	192	179	179
query46	1060	1185	744	744
query47	2320	2320	2179	2179
query48	419	435	296	296
query49	593	443	342	342
query50	1008	447	347	347
query51	10538	10776	10704	10704
query52	87	89	76	76
query53	279	290	207	207
query54	294	248	239	239
query55	78	75	70	70
query56	335	326	289	289
query57	1456	1423	1316	1316
query58	294	276	260	260
query59	1594	1618	1467	1467
query60	305	286	271	271
query61	179	215	154	154
query62	692	650	592	592
query63	234	202	205	202
query64	2798	1019	848	848
query65	4872	4781	4744	4744
query66	1790	503	386	386
query67	28869	29385	29293	29293
query68	3025	1640	934	934
query69	411	299	260	260
query70	1044	962	960	960
query71	351	304	303	303
query72	3009	2712	2365	2365
query73	836	747	449	449
query74	5136	4924	4719	4719
query75	2616	2552	2190	2190
query76	2318	1182	781	781
query77	341	392	272	272
query78	12291	12235	11732	11732
query79	1407	1119	726	726
query80	1336	532	447	447
query81	543	319	270	270
query82	574	157	123	123
query83	389	312	291	291
query84	280	157	126	126
query85	1009	597	495	495
query86	427	310	275	275
query87	1823	1826	1714	1714
query88	3683	2783	2769	2769
query89	456	401	356	356
query90	1901	193	190	190
query91	197	186	162	162
query92	60	61	53	53
query93	1588	1593	1017	1017
query94	724	343	326	326
query95	758	479	463	463
query96	1112	772	351	351
query97	2676	2659	2529	2529
query98	214	206	196	196
query99	1141	1185	1031	1031
Total cold run time: 264165 ms
Total hot run time: 179358 ms

@hello-stephen

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

query1	0.00	0.00	0.00
query2	0.17	0.08	0.09
query3	0.38	0.25	0.25
query4	1.61	0.24	0.24
query5	0.33	0.31	0.32
query6	1.16	0.67	0.66
query7	0.04	0.01	0.01
query8	0.09	0.08	0.07
query9	0.50	0.37	0.37
query10	0.57	0.57	0.56
query11	0.32	0.20	0.18
query12	0.31	0.19	0.18
query13	0.51	0.52	0.52
query14	0.93	0.92	0.92
query15	0.68	0.60	0.60
query16	0.38	0.39	0.39
query17	0.97	1.01	1.01
query18	0.30	0.29	0.29
query19	1.91	1.76	1.81
query20	0.02	0.01	0.01
query21	15.44	0.40	0.31
query22	4.70	0.14	0.13
query23	15.83	0.51	0.30
query24	2.36	0.58	0.43
query25	0.15	0.11	0.10
query26	0.74	0.26	0.21
query27	0.11	0.11	0.10
query28	3.50	0.93	0.52
query29	12.49	4.24	3.25
query30	0.37	0.26	0.26
query31	2.77	0.62	0.33
query32	3.23	0.60	0.46
query33	2.98	2.97	2.95
query34	15.71	4.12	3.35
query35	3.29	3.27	3.26
query36	0.63	0.53	0.52
query37	0.12	0.10	0.09
query38	0.08	0.07	0.07
query39	0.07	0.06	0.06
query40	0.20	0.20	0.17
query41	0.13	0.08	0.08
query42	0.09	0.06	0.06
query43	0.08	0.07	0.07
Total cold run time: 96.25 s
Total hot run time: 25.49 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 48.11% (51/106) 🎉
Increment coverage report
Complete coverage report

@Gabriel39

Copy link
Copy Markdown
Contributor

/review

### What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary: COUNT(nullable complex column) over Parquet or ORC file TVFs cannot use COUNT(*) row metadata because top-level NULL values must be excluded. With FileScannerV2, the query therefore decoded the full complex column through Arrow and then materialized Doris columns, retaining decoded binary chunks and causing excessive peak memory or intermittent OOM. This change introduces an explicit COUNT_NON_NULL operation and target slot from FE to BE. Parquet counts top-level shape from bounded definition/repetition-level batches without Arrow builders or Doris value columns, while ORC uses non-null stripe statistics. It also emits valid non-NULL synthetic target rows and releases file-block ownership before mutable output conversion to avoid unnecessary COW copies.

### Release note

Reduce memory usage for COUNT on nullable columns read from Parquet and ORC file TVFs with FileScannerV2.

### Check List (For Author)

- Test: Unit Test
    - FE PhysicalStorageLayerAggregateTest: 4 tests passed
    - BE targeted Parquet, ORC, and TableReader tests: 14 tests passed
    - HDFS TVF regression assertion added but not run locally because this worktree has no Doris cluster or external HDFS test environment
- Behavior changed: Yes. Eligible nullable file-column counts use explicit COUNT_NON_NULL pushdown instead of materializing the full column.
- Does this need documentation: No
@xylaaaaa xylaaaaa force-pushed the codex/fix-v2-count-complex-memory-pr branch from 994746b to ef14917 Compare July 14, 2026 02:34
@xylaaaaa

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.

I found one correctness issue in the new COUNT_NON_NULL pushdown path. The PR head moved after the review snapshot, so I fetched and rechecked live head ef14917; the issue still exists at the submitted anchor.

Checkpoint summary:

  • Correctness: COUNT_NON_NULL currently fails valid count(col) queries when the per-split mapping or file reader cannot serve the optimization, instead of falling back to a normal scan.
  • Lifecycle/concurrency: runtime-filter, conjunct, delete, condition-cache, close, and finalize ownership paths were checked; no separate issue remained.
  • Compatibility/config: TVF format gating, session-variable gates, thrift propagation, and SlotId-to-GlobalIndex mapping were checked.
  • Tests: existing tests cover successful direct Parquet/ORC paths, but not fallback for missing/defaulted split columns or unsupported reader metadata/layouts. No tests were run in this review environment.

FileAggregateResult file_result;
const auto status = _data_reader.reader->get_aggregate_result(file_request, &file_result);
if (status.is<ErrorCode::NOT_IMPLEMENTED_ERROR>()) {
if (_push_down_agg_type == TPushAggOp::type::COUNT_NON_NULL) {

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 makes an optional pushdown miss fail the query. Status::NotSupported is NOT_IMPLEMENTED_ERROR, and the Parquet/ORC aggregate readers still return it for cases they cannot answer from metadata or levels, such as unsupported Parquet nested layouts or missing ORC stripe/column statistics. The per-split mapper can also reject the target when a TVF glob contains a later file where the column is missing/defaulted; the normal scan path can synthesize those values. Since the scan still has the real count column projected, COUNT_NON_NULL needs the same fallback behavior as COUNT/MINMAX: leave pushed_down=false and scan rows normally instead of returning an error for valid count(col) queries.

@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/29300959927

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

@hello-stephen

Copy link
Copy Markdown
Contributor

Cloud UT Coverage Report

Increment line coverage 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 77.39% (1896/2450)
Line Coverage 64.45% (34072/52862)
Region Coverage 64.85% (17529/27032)
Branch Coverage 54.02% (9394/17390)

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17693	4071	4028	4028
q2	2040	338	210	210
q3	10883	1479	823	823
q4	4822	472	342	342
q5	8488	879	573	573
q6	357	169	136	136
q7	859	863	611	611
q8	10703	1536	1537	1536
q9	5772	4320	4304	4304
q10	6812	1778	1465	1465
q11	512	345	316	316
q12	710	543	427	427
q13	18080	3392	2785	2785
q14	273	263	251	251
q15	q16	791	790	712	712
q17	1011	1006	947	947
q18	6819	5809	5499	5499
q19	1183	1302	1053	1053
q20	758	677	552	552
q21	5606	2638	2274	2274
q22	431	355	295	295
Total cold run time: 104603 ms
Total hot run time: 29139 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4390	4274	4307	4274
q2	294	323	214	214
q3	4559	4975	4425	4425
q4	2074	2177	1454	1454
q5	4356	4218	4269	4218
q6	220	178	127	127
q7	2217	1926	1606	1606
q8	2514	2117	2152	2117
q9	7885	7712	7784	7712
q10	4766	4658	4229	4229
q11	730	395	381	381
q12	764	757	550	550
q13	3276	3663	3068	3068
q14	287	295	283	283
q15	q16	697	754	661	661
q17	1347	1335	1329	1329
q18	7989	7423	7120	7120
q19	1145	1055	1072	1055
q20	2210	2220	1992	1992
q21	5206	4507	4373	4373
q22	506	453	415	415
Total cold run time: 57432 ms
Total hot run time: 51603 ms

@hello-stephen

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

query5	4347	622	481	481
query6	466	225	202	202
query7	4865	647	353	353
query8	362	199	176	176
query9	8780	4124	4020	4020
query10	488	353	323	323
query11	5954	2326	2109	2109
query12	159	103	103	103
query13	1269	629	408	408
query14	6209	5239	4951	4951
query14_1	4342	4270	4294	4270
query15	214	203	183	183
query16	1032	465	427	427
query17	1126	742	555	555
query18	2443	465	341	341
query19	208	182	143	143
query20	113	109	102	102
query21	231	155	131	131
query22	13567	13668	13345	13345
query23	17326	16503	16043	16043
query23_1	16234	16193	16261	16193
query24	7535	1764	1280	1280
query24_1	1334	1292	1277	1277
query25	545	435	354	354
query26	1321	359	209	209
query27	2590	575	387	387
query28	4485	2034	1969	1969
query29	1055	608	474	474
query30	349	271	241	241
query31	1126	1092	977	977
query32	111	65	59	59
query33	507	312	248	248
query34	1145	1150	655	655
query35	757	778	667	667
query36	1169	1192	1036	1036
query37	155	104	90	90
query38	1869	1703	1636	1636
query39	880	899	853	853
query39_1	834	843	861	843
query40	256	169	145	145
query41	72	68	69	68
query42	99	96	96	96
query43	320	326	281	281
query44	1430	786	767	767
query45	202	191	178	178
query46	1051	1210	742	742
query47	2167	2164	2077	2077
query48	408	439	298	298
query49	607	436	313	313
query50	1076	409	331	331
query51	10765	10657	10535	10535
query52	90	93	75	75
query53	261	278	204	204
query54	316	260	242	242
query55	79	73	73	73
query56	320	306	304	304
query57	1326	1312	1193	1193
query58	307	275	278	275
query59	1592	1652	1443	1443
query60	325	285	265	265
query61	177	178	173	173
query62	540	512	444	444
query63	246	201	199	199
query64	2982	1202	861	861
query65	4737	4576	4645	4576
query66	1842	483	369	369
query67	29447	29303	29216	29216
query68	3345	1638	1037	1037
query69	414	309	269	269
query70	1052	966	949	949
query71	357	343	278	278
query72	3057	2686	2403	2403
query73	831	810	459	459
query74	5087	4942	4704	4704
query75	2506	2494	2116	2116
query76	2329	1171	796	796
query77	354	369	280	280
query78	11932	11896	11305	11305
query79	1382	1084	726	726
query80	1294	528	448	448
query81	521	322	274	274
query82	606	154	120	120
query83	382	323	303	303
query84	294	171	134	134
query85	1022	612	516	516
query86	434	308	289	289
query87	1830	1815	1781	1781
query88	3749	2843	2790	2790
query89	445	365	320	320
query90	1948	205	199	199
query91	204	192	158	158
query92	64	60	54	54
query93	1691	1566	972	972
query94	729	336	303	303
query95	775	585	468	468
query96	1108	819	329	329
query97	2642	2612	2471	2471
query98	217	226	202	202
query99	1093	1114	971	971
Total cold run time: 264571 ms
Total hot run time: 177574 ms

@hello-stephen

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

query1	0.01	0.00	0.01
query2	0.18	0.09	0.08
query3	0.39	0.24	0.23
query4	1.61	0.24	0.24
query5	0.34	0.32	0.31
query6	1.17	0.66	0.67
query7	0.04	0.00	0.00
query8	0.09	0.07	0.07
query9	0.51	0.38	0.38
query10	0.59	0.58	0.57
query11	0.31	0.18	0.17
query12	0.31	0.19	0.20
query13	0.52	0.53	0.51
query14	0.93	0.93	0.92
query15	0.69	0.61	0.59
query16	0.38	0.40	0.39
query17	0.99	1.00	0.98
query18	0.30	0.30	0.29
query19	1.96	1.86	1.80
query20	0.02	0.01	0.02
query21	15.44	0.37	0.32
query22	4.83	0.15	0.14
query23	15.78	0.50	0.31
query24	2.43	0.62	0.44
query25	0.16	0.11	0.10
query26	0.74	0.27	0.22
query27	0.11	0.10	0.10
query28	3.49	0.91	0.54
query29	12.46	4.13	3.25
query30	0.37	0.27	0.27
query31	2.76	0.63	0.34
query32	3.24	0.59	0.47
query33	3.07	2.95	2.92
query34	15.66	4.05	3.41
query35	3.31	3.27	3.26
query36	0.63	0.53	0.49
query37	0.12	0.10	0.09
query38	0.08	0.07	0.06
query39	0.08	0.06	0.06
query40	0.20	0.17	0.16
query41	0.13	0.08	0.09
query42	0.08	0.06	0.07
query43	0.07	0.07	0.06
Total cold run time: 96.58 s
Total hot run time: 25.54 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 71.48% (183/256) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 74.74% (30254/40479)
Line Coverage 58.83% (332721/565543)
Region Coverage 55.45% (278449/502203)
Branch Coverage 56.81% (123426/217248)

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 18.21% (55/302) 🎉
Increment coverage report
Complete coverage report

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