Skip to content

[fix](iceberg) Honor disabled write metrics#65782

Open
Gabriel39 wants to merge 9 commits into
apache:masterfrom
Gabriel39:ai/doris-27023-iceberg-write-metrics
Open

[fix](iceberg) Honor disabled write metrics#65782
Gabriel39 wants to merge 9 commits into
apache:masterfrom
Gabriel39:ai/doris-27023-iceberg-write-metrics

Conversation

@Gabriel39

@Gabriel39 Gabriel39 commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • honor Iceberg table metrics configuration when Doris creates data-file metadata
  • omit all column metrics whose effective Iceberg metrics mode is none
  • omit bounds for counts and safely truncate string/binary bounds for truncate(N)
  • build the table metrics policy once per commit batch instead of once per output file
  • return unknown Iceberg column statistics when required file metrics are absent
  • preserve unknown statistics when closing an Iceberg file scan fails
  • add regression coverage for the write-to-statistics path

Root cause

Doris collected column statistics in the backend and copied every statistics map into the Iceberg DataFile manifest in the frontend. The conversion never consulted the table's MetricsConfig, so metadata for disabled columns was persisted even though the physical file statistics were available only as an implementation detail. The initial filtering also treated every non-none mode like full, retaining bounds for counts and failing to safely truncate string/binary bounds for truncate(N).

After disabled metrics were correctly omitted, the downstream Iceberg statistics reader still assumed columnSizes and nullValueCounts always contained every column. It could therefore throw while loading statistics for a table using metrics mode none. A scan-close failure could also override an in-flight unknown-statistics return and expose partial or fabricated accumulators. The reader now treats missing required metrics and scan-close failures as unknown.

Testing

  • IcebergWriterHelperTest and StatisticsUtilTest (21 tests passed)
  • verified the new review regression tests fail before their production fixes and pass after them
  • FE CheckStyle validation (0 violations)
  • git diff --check

Links

Jira: DORIS-27023

Filter backend-collected file statistics using the Iceberg table metrics configuration before writing manifest metadata.
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

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

@Gabriel39
Gabriel39 marked this pull request as ready for review July 18, 2026 11:59
@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17641	4153	4130	4130
q2	1996	322	201	201
q3	10347	1428	816	816
q4	4711	472	335	335
q5	7632	854	572	572
q6	212	171	140	140
q7	787	808	610	610
q8	10264	1682	1590	1590
q9	6044	4336	4304	4304
q10	6782	1722	1446	1446
q11	508	353	321	321
q12	780	575	446	446
q13	18081	3294	2703	2703
q14	261	260	262	260
q15	q16	786	783	701	701
q17	955	1006	963	963
q18	6854	5707	5490	5490
q19	1557	1264	1049	1049
q20	816	680	583	583
q21	5977	2570	2583	2570
q22	425	357	307	307
Total cold run time: 103416 ms
Total hot run time: 29537 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4510	4391	4395	4391
q2	270	309	207	207
q3	4565	4904	4402	4402
q4	2049	2115	1359	1359
q5	4401	4263	4252	4252
q6	224	179	127	127
q7	2037	1981	1591	1591
q8	2533	2170	2167	2167
q9	7879	7805	7711	7711
q10	4699	4631	4236	4236
q11	571	423	376	376
q12	879	807	532	532
q13	3272	3543	3049	3049
q14	320	320	308	308
q15	q16	712	713	649	649
q17	1367	1357	1359	1357
q18	7897	7299	7098	7098
q19	1153	1061	1095	1061
q20	2238	2206	1929	1929
q21	5228	4560	4428	4428
q22	542	444	433	433
Total cold run time: 57346 ms
Total hot run time: 51663 ms

@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 two issues that should be addressed before merge.

Checkpoint conclusions:

  • Goal and data correctness: the new effective-none filtering matches Iceberg 1.10.1 for all five populated metric maps and is shared by insert/overwrite, merge/row-delta, and rewrite commits. However, Doris's enabled HMS Iceberg statistics-fetch path cannot consume the newly absent maps and falls back to UNKNOWN through repeated exceptions.
  • Scope and parallel paths: the production change is focused, and both BE Parquet and ORC payloads converge on this helper. The downstream statistics consumer is the only direct Java ContentFile metrics consumer found with an absent-map assumption.
  • Concurrency and lifecycle: conversion is synchronous; Iceberg's transaction table reads one non-refreshing metadata snapshot, so there is no cross-file schema/property race or lock-order issue. That same stability makes rebuilding the table policy for every file unnecessary.
  • Configuration and compatibility: no Doris config, FE-BE protocol, function symbol, or storage-format field is added. Omitting optional manifest maps for effective none is standard Iceberg behavior, but enable_fetch_iceberg_stats needs an explicit missing-metrics fallback.
  • Transactions, persistence, and writes: append, replace, row-delta, and rewrite transaction mechanics are unchanged; manifest persistence is the intended behavior. No EditLog path applies to this external Iceberg commit.
  • Testing: the new unit test covers the direct global-none helper result but not the write-to-statistics consumer failure. Per the review-runner contract I did not build locally. CheckStyle passes. The current FE UT job is red because Maven received a truncated paimon-s3 dependency before fe-core; 293 earlier tests passed, so this is infrastructure failure and the changed test did not execute in that job. The author-reported targeted 7-test result was not independently rerun here.
  • Observability: existing cache-loader logging exposes the exception but does not make the configured statistics feature work; no separate metrics/logging change otherwise appears necessary.
  • User focus: no additional focus points were supplied.

Please address the two inline comments and add the missing absent-metrics coverage.


return new Metrics(commitData.getRowCount(), columnSizes, valueCounts,
nullValueCounts, null, lowerBounds, upperBounds);
MetricsConfig metricsConfig = MetricsConfig.forTable(table);

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] Build the metrics policy once per file batch

convertToWriterResult invokes this method once for every TIcebergCommitData, so these new lines rebuild the same MetricsConfig and fetch the same schema for every output file. MetricsConfig.forTable walks schema field IDs/inferred defaults, sort columns, and properties; partition-heavy or heavily rolled writes therefore repeat fixed table work F times on the synchronous FE commit path. The transaction table's metadata is stable for this batch, so please capture the config/schema once before the loop and pass them into buildDataFileMetrics.

Schema schema = table.schema();
// Physical file stats may contain every column, but manifest metrics must honor the table's metadata policy.
return new Metrics(commitData.getRowCount(),
filterDisabledMetrics(columnSizes, schema, metricsConfig),

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] Handle disabled maps in Iceberg stats fetching

An effective none mode correctly makes both columnSizes() and nullValueCounts() absent, but StatisticsUtil.getIcebergColumnStats still unconditionally adds task.file().columnSizes().get(colId) and task.file().nullValueCounts().get(colId) at lines 608/610. After an HMS Iceberg table is written with this property, enabling enable_fetch_iceberg_stats therefore drives the stats-cache load into a null dereference/fallback for every affected column. Please update that consumer to recognize missing metrics (return unknown/empty rather than aggregating a fabricated zero) and cover the write-to-stats path.

@hello-stephen

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

query5	4335	634	500	500
query6	455	230	210	210
query7	4844	576	346	346
query8	332	196	168	168
query9	8788	4043	4062	4043
query10	481	365	339	339
query11	5970	2355	2127	2127
query12	160	108	107	107
query13	1264	602	417	417
query14	6292	5242	4947	4947
query14_1	4279	4262	4256	4256
query15	220	208	182	182
query16	1001	458	441	441
query17	1136	744	585	585
query18	2712	461	345	345
query19	221	196	159	159
query20	120	110	110	110
query21	234	169	137	137
query22	13588	13627	13528	13528
query23	17371	16505	16135	16135
query23_1	16273	16437	16319	16319
query24	7605	1758	1291	1291
query24_1	1296	1321	1276	1276
query25	577	463	411	411
query26	1317	331	213	213
query27	2580	610	385	385
query28	4409	1999	1997	1997
query29	1071	615	467	467
query30	343	263	235	235
query31	1112	1089	988	988
query32	108	65	60	60
query33	519	321	242	242
query34	1178	1137	633	633
query35	749	799	662	662
query36	1184	1191	1071	1071
query37	153	108	99	99
query38	1897	1703	1647	1647
query39	880	860	837	837
query39_1	838	842	852	842
query40	251	163	141	141
query41	66	63	63	63
query42	93	91	92	91
query43	330	334	287	287
query44	1474	775	752	752
query45	196	175	172	172
query46	1060	1197	749	749
query47	2138	2122	2003	2003
query48	397	400	285	285
query49	572	412	305	305
query50	1137	430	337	337
query51	10659	10586	10530	10530
query52	87	90	75	75
query53	259	282	196	196
query54	281	239	216	216
query55	80	70	65	65
query56	297	287	297	287
query57	1307	1254	1207	1207
query58	288	269	260	260
query59	1568	1656	1444	1444
query60	297	277	250	250
query61	146	157	142	142
query62	555	505	438	438
query63	240	204	202	202
query64	2801	1073	845	845
query65	4721	4635	4641	4635
query66	1788	493	386	386
query67	29315	29276	29242	29242
query68	3126	1603	943	943
query69	412	299	262	262
query70	1083	964	985	964
query71	378	331	327	327
query72	3071	2706	2324	2324
query73	884	778	444	444
query74	5069	4897	4723	4723
query75	2547	2506	2138	2138
query76	2338	1182	795	795
query77	357	382	278	278
query78	11895	12024	11341	11341
query79	1402	1237	735	735
query80	775	557	455	455
query81	473	333	289	289
query82	573	160	125	125
query83	386	318	299	299
query84	279	158	133	133
query85	1018	593	535	535
query86	408	282	296	282
query87	1834	1841	1782	1782
query88	3743	2797	2756	2756
query89	447	385	323	323
query90	1835	204	199	199
query91	205	193	155	155
query92	64	59	56	56
query93	1572	1536	991	991
query94	611	354	307	307
query95	805	578	469	469
query96	1128	839	352	352
query97	2594	2623	2496	2496
query98	213	222	197	197
query99	1102	1114	975	975
Total cold run time: 263271 ms
Total hot run time: 178094 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 62adff4e3f83f65758adeda6dd92e19479f3724b, data reload: false

query1	0.01	0.01	0.01
query2	0.09	0.08	0.04
query3	0.25	0.14	0.13
query4	1.60	0.14	0.13
query5	0.24	0.23	0.23
query6	1.27	1.09	1.07
query7	0.05	0.01	0.01
query8	0.07	0.04	0.04
query9	0.38	0.32	0.31
query10	0.56	0.57	0.55
query11	0.20	0.13	0.13
query12	0.18	0.14	0.14
query13	0.47	0.49	0.47
query14	1.02	1.03	1.02
query15	0.60	0.59	0.58
query16	0.31	0.34	0.32
query17	1.11	1.09	1.11
query18	0.23	0.21	0.21
query19	2.09	1.92	1.95
query20	0.02	0.01	0.02
query21	15.45	0.25	0.13
query22	4.82	0.05	0.06
query23	16.12	0.31	0.13
query24	3.01	0.42	0.33
query25	0.10	0.05	0.04
query26	0.73	0.22	0.15
query27	0.04	0.04	0.03
query28	3.49	0.88	0.56
query29	12.52	4.19	3.32
query30	0.28	0.15	0.17
query31	2.77	0.61	0.32
query32	3.22	0.59	0.49
query33	3.34	3.26	3.20
query34	15.65	4.18	3.54
query35	3.50	3.51	3.55
query36	0.55	0.44	0.43
query37	0.08	0.07	0.06
query38	0.05	0.04	0.03
query39	0.04	0.03	0.03
query40	0.17	0.17	0.16
query41	0.08	0.03	0.03
query42	0.03	0.02	0.02
query43	0.04	0.03	0.04
Total cold run time: 96.83 s
Total hot run time: 25.15 s

Build the Iceberg metrics policy once per commit batch and return unknown statistics when required file metrics are absent.\n\nJira: DORIS-27023
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17611	4082	4047	4047
q2	2005	316	201	201
q3	10301	1407	800	800
q4	4685	479	339	339
q5	7506	840	576	576
q6	178	169	134	134
q7	759	855	607	607
q8	9307	1593	1617	1593
q9	5554	4375	4340	4340
q10	6749	1729	1466	1466
q11	518	362	326	326
q12	716	590	446	446
q13	18169	3471	2804	2804
q14	267	263	249	249
q15	q16	782	779	706	706
q17	967	953	915	915
q18	6871	5736	5656	5656
q19	1208	1198	1011	1011
q20	787	694	549	549
q21	5690	2537	2314	2314
q22	420	347	295	295
Total cold run time: 101050 ms
Total hot run time: 29374 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4396	4313	4287	4287
q2	286	314	215	215
q3	4574	4998	4341	4341
q4	2042	2170	1362	1362
q5	4459	4252	4274	4252
q6	229	176	126	126
q7	1726	1618	1861	1618
q8	2662	2186	2200	2186
q9	7972	8115	7676	7676
q10	4670	4701	4271	4271
q11	583	400	378	378
q12	772	764	553	553
q13	3467	3658	2964	2964
q14	321	306	265	265
q15	q16	721	731	661	661
q17	1357	1333	1322	1322
q18	8003	7242	7224	7224
q19	1175	1135	1146	1135
q20	2231	2201	1933	1933
q21	5215	4569	4364	4364
q22	513	461	397	397
Total cold run time: 57374 ms
Total hot run time: 51530 ms

@hello-stephen

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

query5	4342	695	506	506
query6	483	231	219	219
query7	4844	625	359	359
query8	342	204	183	183
query9	8831	4131	4087	4087
query10	499	365	306	306
query11	5966	2434	2148	2148
query12	168	104	100	100
query13	1246	588	408	408
query14	6336	5618	5229	5229
query14_1	4589	4600	4592	4592
query15	225	211	186	186
query16	1013	475	395	395
query17	958	751	606	606
query18	2452	489	362	362
query19	214	193	158	158
query20	117	111	108	108
query21	248	169	140	140
query22	13769	13707	13498	13498
query23	17657	16725	16392	16392
query23_1	16502	16412	16374	16374
query24	7510	1805	1302	1302
query24_1	1351	1343	1312	1312
query25	617	482	401	401
query26	1340	389	218	218
query27	2562	605	381	381
query28	4514	2025	1977	1977
query29	1084	648	497	497
query30	362	272	242	242
query31	1166	1120	1022	1022
query32	126	66	64	64
query33	532	340	273	273
query34	1199	1231	657	657
query35	826	858	702	702
query36	1192	1206	1025	1025
query37	161	111	94	94
query38	1969	1804	1726	1726
query39	878	893	858	858
query39_1	854	840	841	840
query40	251	180	151	151
query41	72	68	69	68
query42	96	94	97	94
query43	345	357	301	301
query44	1484	794	765	765
query45	207	193	181	181
query46	1084	1192	728	728
query47	2120	2088	2004	2004
query48	401	403	284	284
query49	598	435	329	329
query50	1098	435	348	348
query51	10654	10802	10515	10515
query52	93	97	82	82
query53	275	287	213	213
query54	300	257	236	236
query55	76	75	68	68
query56	323	329	308	308
query57	1297	1296	1188	1188
query58	347	294	284	284
query59	1680	1762	1495	1495
query60	304	273	242	242
query61	152	150	145	145
query62	567	503	434	434
query63	245	208	206	206
query64	2819	1053	850	850
query65	4853	4791	4752	4752
query66	1829	513	386	386
query67	29473	28933	29385	28933
query68	3255	1577	1000	1000
query69	427	307	277	277
query70	1092	1024	980	980
query71	407	332	342	332
query72	3159	2733	2436	2436
query73	855	785	446	446
query74	5144	5000	4746	4746
query75	2610	2529	2148	2148
query76	2299	1261	839	839
query77	369	402	293	293
query78	11959	12006	11289	11289
query79	1427	1161	733	733
query80	684	579	457	457
query81	483	346	301	301
query82	571	158	127	127
query83	383	324	309	309
query84	321	168	130	130
query85	960	623	528	528
query86	360	296	287	287
query87	1921	1895	1810	1810
query88	3761	2782	2760	2760
query89	449	396	317	317
query90	1950	213	206	206
query91	204	198	163	163
query92	62	61	58	58
query93	1582	1575	908	908
query94	573	337	323	323
query95	806	545	574	545
query96	1085	863	339	339
query97	2694	2648	2557	2557
query98	216	209	200	200
query99	1117	1103	966	966
Total cold run time: 265532 ms
Total hot run time: 181069 ms

@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 correctness issue in the close-error path. The normal-path changes address the two earlier inline concerns: Iceberg's effective none policy is applied once per file batch, and missing required metrics now produce unknown statistics when the scan closes normally.

Checkpoint conclusions:

  • Goal and data correctness: effective-none filtering matches Iceberg 1.10.1 across global defaults, per-column overrides, wide-schema inferred defaults, and sorted-column promotion. However, the new early Optional.empty() result can still be replaced by partial or fabricated-zero statistics when closing the scan throws; see the inline comment.
  • Scope and parallel paths: the production change is focused. Append, overwrite, merge/row-delta, and rewrite data files all converge on convertToWriterResult; HMS Iceberg statistics converge on getIcebergColumnStats. No additional unmodified parallel path was found.
  • Concurrency and lifecycle: the conversion uses method-local state and adds no threads or locks. Iceberg's transaction table is non-refreshing, so policy/schema hoisting observes one transaction-local metadata snapshot. The remaining lifecycle defect is limited to the try-with-resources close-error completion path.
  • Configuration and compatibility: no Doris config, Thrift field, function symbol, EditLog format, or storage-format field is added. Omitting optional manifest metric maps for effective none is standard Iceberg behavior, and mixed old/new files conservatively return unknown on the normal path.
  • Transactions, persistence, and writes: existing Iceberg commit atomicity, visibility, cleanup, and append/overwrite/merge/rewrite mechanics are unchanged; only DataFile manifest metrics are affected.
  • Error handling and observability: absent maps or entries correctly invalidate the whole aggregation on normal close, and the existing warning identifies close failures. The catch must also preserve the unavailable result instead of allowing accumulator state to escape.
  • Performance: MetricsConfig and schema work is now performed once per batch; per-file filtering is linear in supplied metric entries. No additional hot-path issue was substantiated.
  • Testing: the new JUnit tests cover global none, once-per-batch policy construction, and the normal write-to-statistics fallback. They use a no-op close and therefore miss the accepted close-IOException path. Per the review-runner contract I did not build or run tests locally.
  • User focus: no additional focus points were supplied.

Please address the inline issue and add throwing-close coverage.

Long nullValueCount = nullValueCounts == null ? null : nullValueCounts.get(colId);
// Iceberg can omit maps or entries for mode=none; partial aggregation would fabricate zero stats.
if (columnSize == null || nullValueCount == null) {
return Optional.empty();

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] Preserve unknown stats when closing the scan fails

This return runs inside try-with-resources. If CloseableIterable.close() throws IOException, Java abandons the pending Optional.empty() return, enters the catch below, and then builds a statistic from the current accumulators. For example, a complete file followed by a metrics-disabled file will expose partial totals if close also fails; if the disabled file is first, it exposes a fabricated zero statistic. Please return Optional.empty() from the IOException catch (or otherwise preserve the unavailable state) and cover a throwing-close iterable. This is distinct from the prior missing-map thread: normal close is fixed here, while the close-error path still escapes partial data.

@hello-stephen

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

query1	0.00	0.00	0.00
query2	0.09	0.05	0.05
query3	0.25	0.14	0.14
query4	1.62	0.14	0.14
query5	0.27	0.23	0.22
query6	1.23	1.07	1.05
query7	0.04	0.00	0.01
query8	0.06	0.04	0.04
query9	0.37	0.31	0.31
query10	0.54	0.56	0.55
query11	0.20	0.14	0.14
query12	0.18	0.14	0.14
query13	0.48	0.47	0.47
query14	1.01	1.02	1.02
query15	0.62	0.58	0.63
query16	0.31	0.31	0.30
query17	1.07	1.06	1.10
query18	0.24	0.21	0.21
query19	2.08	1.85	1.91
query20	0.01	0.01	0.01
query21	15.44	0.24	0.13
query22	4.72	0.05	0.05
query23	16.12	0.30	0.12
query24	3.11	0.43	0.32
query25	0.10	0.05	0.04
query26	0.72	0.21	0.15
query27	0.03	0.04	0.03
query28	3.55	0.90	0.54
query29	12.49	4.05	3.28
query30	0.28	0.15	0.16
query31	2.77	0.58	0.31
query32	3.22	0.60	0.48
query33	3.24	3.18	3.22
query34	15.55	4.27	3.54
query35	3.50	3.51	3.52
query36	0.56	0.43	0.42
query37	0.08	0.07	0.06
query38	0.05	0.04	0.03
query39	0.04	0.03	0.03
query40	0.18	0.16	0.15
query41	0.08	0.03	0.03
query42	0.05	0.03	0.02
query43	0.04	0.03	0.04
Total cold run time: 96.59 s
Total hot run time: 24.88 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 69.57% (16/23) 🎉
Increment coverage report
Complete coverage report

Return unknown Iceberg column statistics when closing the scan fails, preventing partial or zero accumulators from escaping.

Jira: DORIS-27023
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

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.

Automated review: changes requested

The current head correctly omits metrics for effective none mode, builds the table policy once per batch, and returns unknown statistics when required file metrics are absent or scan close fails. One blocking configuration-semantics issue remains: counts and truncate(N) are still treated like full for bound maps (see inline comment).

Critical checkpoint conclusions:

  • Goal and test proof: Partially achieved. The new tests cover none, batch policy construction, missing metrics, and close failure, but do not cover counts or truncate(N), which exposes the remaining defect.
  • Scope and clarity: The four-file FE change is focused and reuses the central data-file conversion path.
  • Concurrency and lifecycle: No new shared mutable state, locks, threads, static initialization, or special owner lifecycle; CloseableIterable is managed by try-with-resources and close failure now preserves unknown statistics.
  • Configuration, compatibility, and persistence: No new config or Doris protocol field is introduced, and optional Iceberg manifest maps remain format-compatible. However, existing Iceberg metrics properties are not fully honored because raw full bounds are persisted for counts and string/binary truncate(N).
  • Parallel paths, transactions, and data writes: Insert/overwrite, merge/row-delta, and rewrite all converge on convertToWriterResult; Parquet and ORC producers were traced. No separate atomicity, failover, or path-propagation issue was found.
  • Error handling, conditions, and observability: Missing maps/entries and checked close failures now fail conservatively to unknown statistics. Existing cache-loader/log boundaries are adequate; no additional metric is needed.
  • Performance: Policy/schema construction is amortized per batch as intended. No other material hot-path regression was substantiated.
  • Validation: Static review only, as required by the runner contract; no local build or test was run. The added JUnit counterfactuals for the already-known regressions were inspected, and GitHub CheckStyle was green during review.
  • User focus: No additional user-provided focus was specified.

Review completeness: The complete authoritative diff, changed-file list, existing threads, producer/consumer paths, tests, and applicable Doris checkpoints were reviewed. Every candidate was verified and deduplicated; MAIN-1 is the only distinct issue to submit.

Map<Integer, T> metrics, Schema schema, MetricsConfig metricsConfig) {
Map<Integer, T> filteredMetrics = new HashMap<>();
metrics.forEach((fieldId, value) -> {
if (MetricsUtil.metricsMode(schema, metricsConfig, fieldId) != MetricsModes.None.get()) {

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] Apply the effective mode to each metric family

Every non-None mode passes through the same raw maps here. With write.metadata.metrics.default=counts, the BE-provided lower/upper bounds are still written even though Iceberg counts mode must omit them; with the normal truncate(16) default (and explicit or sort-promoted truncate modes), long string/binary bounds are copied in full instead of using Iceberg's safe lower/upper truncation. The BE producers emit complete footer extrema and DataFiles.Builder.withMetrics does not reapply MetricsConfig, so these full values reach manifests. Please make bound handling mode-aware—drop bounds for counts and decode/truncate/re-encode string/binary bounds for truncate(N)—and add counts/truncate tests.

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17706	3936	3934	3934
q2	2023	317	198	198
q3	10282	1367	833	833
q4	4690	467	332	332
q5	7478	859	567	567
q6	187	178	151	151
q7	737	803	602	602
q8	9881	1466	1506	1466
q9	6233	4274	4246	4246
q10	6777	1709	1464	1464
q11	514	359	318	318
q12	750	565	446	446
q13	18114	3237	2725	2725
q14	268	254	244	244
q15	q16	778	761	710	710
q17	1042	987	935	935
q18	6983	5842	5461	5461
q19	1257	1261	1080	1080
q20	776	673	556	556
q21	5747	2671	2304	2304
q22	421	351	295	295
Total cold run time: 102644 ms
Total hot run time: 28867 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4315	4217	4260	4217
q2	274	305	207	207
q3	4559	4904	4390	4390
q4	2050	2159	1343	1343
q5	4318	4216	4205	4205
q6	231	175	128	128
q7	1694	1600	1832	1600
q8	2593	2132	2134	2132
q9	7669	7724	7569	7569
q10	4759	4620	4171	4171
q11	551	417	424	417
q12	736	747	527	527
q13	3250	3635	2970	2970
q14	318	310	276	276
q15	q16	701	744	661	661
q17	1349	1302	1314	1302
q18	7977	7301	7050	7050
q19	1065	1070	1052	1052
q20	2199	2199	1924	1924
q21	5149	4515	4335	4335
q22	517	447	397	397
Total cold run time: 56274 ms
Total hot run time: 50873 ms

@hello-stephen

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

query5	4331	656	494	494
query6	463	236	213	213
query7	4850	596	342	342
query8	344	195	176	176
query9	8749	4116	4099	4099
query10	449	389	313	313
query11	5872	2385	2122	2122
query12	165	102	104	102
query13	1274	612	416	416
query14	6250	5275	4948	4948
query14_1	4317	4283	4317	4283
query15	209	208	183	183
query16	999	496	451	451
query17	1126	713	581	581
query18	2496	482	349	349
query19	220	198	149	149
query20	114	107	107	107
query21	235	157	138	138
query22	13562	13504	13343	13343
query23	17406	16575	16106	16106
query23_1	16243	16086	16242	16086
query24	7419	1795	1287	1287
query24_1	1328	1290	1291	1290
query25	562	475	392	392
query26	1328	363	225	225
query27	2536	619	377	377
query28	5188	1981	1999	1981
query29	1093	642	516	516
query30	357	275	229	229
query31	1129	1103	1025	1025
query32	129	62	61	61
query33	536	321	265	265
query34	1907	1202	653	653
query35	783	798	683	683
query36	1201	1229	1089	1089
query37	156	106	92	92
query38	1918	1719	1676	1676
query39	924	905	918	905
query39_1	875	849	869	849
query40	245	168	148	148
query41	78	82	62	62
query42	103	93	96	93
query43	335	341	285	285
query44	1511	832	776	776
query45	204	192	189	189
query46	1061	1233	718	718
query47	2094	2069	1932	1932
query48	406	429	301	301
query49	587	412	300	300
query50	1045	434	346	346
query51	10423	10762	10936	10762
query52	86	86	75	75
query53	259	276	200	200
query54	288	234	227	227
query55	74	69	67	67
query56	316	299	277	277
query57	1285	1281	1190	1190
query58	276	269	249	249
query59	1606	1686	1507	1507
query60	315	269	253	253
query61	150	148	150	148
query62	542	497	426	426
query63	277	208	204	204
query64	2838	1026	836	836
query65	4724	4651	4649	4649
query66	1815	509	389	389
query67	29297	29264	29187	29187
query68	3250	1577	979	979
query69	424	292	275	275
query70	1086	978	984	978
query71	374	334	299	299
query72	2973	2659	2351	2351
query73	820	773	420	420
query74	5127	4924	4752	4752
query75	2543	2496	2126	2126
query76	2314	1194	800	800
query77	364	388	289	289
query78	11828	11789	11394	11394
query79	1425	1146	759	759
query80	1322	571	465	465
query81	539	339	290	290
query82	602	156	121	121
query83	371	368	302	302
query84	294	165	125	125
query85	965	623	511	511
query86	422	313	267	267
query87	1826	1820	1740	1740
query88	3778	2798	2777	2777
query89	448	382	339	339
query90	1918	210	200	200
query91	201	188	162	162
query92	63	59	53	53
query93	1663	1518	978	978
query94	735	343	298	298
query95	786	598	506	506
query96	1075	752	358	358
query97	2603	2610	2515	2515
query98	208	203	206	203
query99	1089	1121	974	974
Total cold run time: 265116 ms
Total hot run time: 178692 ms

@hello-stephen

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

query1	0.00	0.00	0.01
query2	0.10	0.05	0.05
query3	0.25	0.14	0.13
query4	1.61	0.14	0.14
query5	0.24	0.22	0.22
query6	1.22	1.04	1.08
query7	0.04	0.01	0.00
query8	0.05	0.03	0.03
query9	0.38	0.31	0.33
query10	0.55	0.54	0.53
query11	0.18	0.13	0.13
query12	0.18	0.14	0.14
query13	0.46	0.46	0.48
query14	1.01	1.00	1.00
query15	0.63	0.59	0.59
query16	0.31	0.31	0.31
query17	1.05	1.06	1.13
query18	0.22	0.21	0.21
query19	2.03	1.87	1.91
query20	0.02	0.01	0.01
query21	15.41	0.22	0.13
query22	4.84	0.05	0.05
query23	16.12	0.30	0.11
query24	2.97	0.41	0.32
query25	0.12	0.05	0.05
query26	0.72	0.19	0.14
query27	0.04	0.04	0.04
query28	3.50	0.89	0.54
query29	12.47	4.16	3.32
query30	0.27	0.18	0.15
query31	2.76	0.58	0.32
query32	3.22	0.60	0.49
query33	3.23	3.27	3.11
query34	15.55	4.26	3.55
query35	3.55	3.56	3.50
query36	0.54	0.41	0.41
query37	0.09	0.06	0.07
query38	0.05	0.04	0.04
query39	0.04	0.03	0.03
query40	0.18	0.16	0.15
query41	0.08	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.03	0.04
Total cold run time: 96.36 s
Total hot run time: 24.83 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 70.83% (17/24) 🎉
Increment coverage report
Complete coverage report

Omit bounds for counts mode and safely truncate string and binary bounds for truncate mode before writing Iceberg manifests.

Jira: DORIS-27023
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17809	4260	4142	4142
q2	2032	312	202	202
q3	10288	1400	847	847
q4	4704	471	342	342
q5	7591	867	580	580
q6	215	182	141	141
q7	793	834	614	614
q8	10329	1584	1570	1570
q9	5867	4367	4359	4359
q10	6790	1730	1478	1478
q11	499	346	332	332
q12	756	588	463	463
q13	18143	3378	2734	2734
q14	258	270	249	249
q15	q16	788	775	713	713
q17	1023	1040	939	939
q18	6914	5708	5570	5570
q19	1243	1298	1028	1028
q20	820	656	563	563
q21	5708	2666	2436	2436
q22	427	360	299	299
Total cold run time: 102997 ms
Total hot run time: 29601 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4509	4481	4497	4481
q2	298	328	222	222
q3	4606	4937	4418	4418
q4	2132	2215	1375	1375
q5	4498	4415	4361	4361
q6	243	183	134	134
q7	2257	1918	1701	1701
q8	2657	2303	2298	2298
q9	7898	7765	7826	7765
q10	4707	4640	4230	4230
q11	640	518	416	416
q12	784	787	563	563
q13	3353	3710	2883	2883
q14	297	314	289	289
q15	q16	714	741	661	661
q17	1428	1378	1413	1378
q18	8199	7579	7119	7119
q19	1116	1105	1090	1090
q20	2215	2215	1941	1941
q21	5453	4848	4660	4660
q22	529	477	415	415
Total cold run time: 58533 ms
Total hot run time: 52400 ms

@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: changes requested

I found three additional issues on the current head: one P1 commit failure and two P2 manifest/performance gaps. I deduplicated them against all four existing inline threads; the new set is limited to the v3 row-lineage schema boundary, repeated-field logical metrics, and all-disabled BE extraction.

Checkpoint conclusions:

  • Goal and proof: The patch now applies Iceberg metrics modes for ordinary fields and preserves unknown statistics, but it does not fully accomplish the goal because v3 row-lineage bounds can fail commit and repeated-field metrics still differ from Iceberg.
  • Scope and focus: The four-file Java change is localized and clear, but the implementation stops after BE collection and uses the table schema where a larger physical write schema is required. No additional user focus was supplied.
  • Concurrency: No new shared mutable state, locks, threads, or ordering hazards are introduced; schema/config objects are batch-local.
  • Lifecycle: The planFiles try-with-resources close-error path now preserves unknown state. No static/global lifecycle is involved. The remaining ORC reopen is a synchronous performance issue, not a leaked resource found in this diff.
  • Configuration: No Doris configuration item is added. Existing Iceberg metrics properties, per-column overrides, and sort-column promotion form the policy being interpreted.
  • Compatibility: The current diff changes no symbol, storage format, or FE-BE wire field. Any upstream all-disabled optimization should preserve collect-by-default behavior for rolling FE/BE compatibility.
  • Parallel paths: Append, overwrite, merge, and rewrite converge on this helper; v3 rewrite and matched mutation paths add writer-only row-lineage fields that the captured table schema omits.
  • Conditions: The ordinary none, counts, and truncate(N) branches are mode-aware, but the filters lack the separate list/map-ancestor rule used by Iceberg.
  • Test coverage: Added JUnit cases cover ordinary none/counts/truncate behavior and one throwing-close path. Missing coverage includes real v3 Parquet/ORC row-lineage callers, null/empty nested list/map data, and proof that all-disabled writes skip BE collection.
  • Test results: The new assertions are consistent with the covered ordinary cases; no generated result file is changed. I did not execute tests because the supplied review contract explicitly prohibits builds and test runs.
  • Observability: No new logging or metrics requirement was identified for this policy transformation.
  • Transactions and persistence: No Doris EditLog or persistence-format change is present. The P1 path is transactionally significant because replacement files are written before manifest conversion fails.
  • Data writes: Manifest metric correctness is part of the Iceberg commit contract; MAIN-1 can abort a supported v3 commit and MAIN-3 publishes misleading repeated-field metadata. No additional write-concurrency issue was found.
  • FE-BE propagation: No new variable is transmitted. That omission is exactly why an effective all-none policy cannot prevent guaranteed-unused BE footer collection.
  • Performance: Building the policy once per batch fixes the prior FE repetition, but all-disabled Parquet footer walks and per-file ORC remote reopens remain.
  • Other issues: The StatisticsUtil missing-map and close-failure handling is now conservative. No further nonduplicate issue survived the final sweep.

Validation was static-only as required. The live head remained a91df699cc3a0c226f2e521f52535cfa1c3bb053, matching the authoritative review bundle, and all three convergence reviewers returned NO_NEW_VALUABLE_FINDINGS against this unchanged comment set.

// Get table specification information
PartitionSpec spec = table.spec();
FileFormat fileFormat = IcebergUtils.getFileFormat(table);
MetricsConfig metricsConfig = MetricsConfig.forTable(table);

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] Skip footer extraction when all metrics are disabled

This policy is first applied on FE after every BE has already populated TIcebergColumnStats. For an unsorted table with write.metadata.metrics.default=none and no column override, VIcebergPartitionWriter still invokes both collectors for every output file; the ORC collector even calls _fs->open_file and creates a new reader for the just-written file before these filters discard every entry. Partition-heavy writes to remote storage therefore pay a guaranteed-unused reopen/footer read plus serialization per file. Please derive/pass an all-disabled decision (accounting for overrides and sort promotion) to the sink and skip BE collection in that case, with an ORC test that verifies no post-close reader is opened.

Map<Integer, T> metrics, Schema schema, MetricsConfig metricsConfig) {
Map<Integer, T> filteredMetrics = new HashMap<>();
metrics.forEach((fieldId, value) -> {
if (MetricsUtil.metricsMode(schema, metricsConfig, fieldId) != MetricsModes.None.get()) {

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] Suppress logical metrics below repeated fields

Separately from the counts/truncate handling in the existing thread, this condition keeps value/null maps for every non-none leaf ID, and filterBounds does the same for bounds. Doris assigns IDs to Parquet list elements and map keys/values, so the BE footer collector sends those physical leaf statistics here. Iceberg 1.10.1 deliberately makes ParquetMetrics.MetricsVisitor.list/map return no descendant value/null/bound metrics (while retaining physical column sizes): definition-level placeholders for a null or empty container cannot be interpreted as logical element nulls. For rows such as NULL, [], and [1, NULL], Doris would publish misleading element counts in $files/readable_metrics. Please index schema ancestry and omit list/map-descendant counts and bounds while retaining their column sizes, with null-container/empty-container/null-element tests.


ByteBuffer filteredValue = value;
if (mode instanceof MetricsModes.Truncate) {
Type type = schema.findType(fieldId);

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] Handle v3 row-lineage IDs before type lookup

For a default-config v3 rewrite_data_files, the sink appends _row_id and _last_updated_sequence_number to the schema sent to BE, and both footer collectors return bounds keyed by those reserved IDs. The commit path calls this helper with transaction.table().schema(), which does not contain the metadata fields. MetricsUtil.metricsMode therefore falls back to the default truncate(16) mode, this lookup returns null, and truncateBound dereferences it at type.typeId(). The existing Parquet/ORC v3 rewrite path will fail after writing the replacement files. Please either apply the policy with the exact write schema or intentionally exclude these metadata IDs before type lookup, and cover the real row-lineage rewrite caller.

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@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.62% (1908/2458)
Line Coverage 64.46% (34140/52966)
Region Coverage 64.90% (17572/27076)
Branch Coverage 54.06% (9419/17424)

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes: one new P2 inline issue remains on the current head.

Review conclusions

  • Goal and correctness: The current head addresses the existing threads for none/counts/truncate/full filtering, repeated descendants, v3 type lookup, downstream unknown statistics, close failures, and avoiding unused footer reads. It does not yet fully honor the effective metrics policy because the new all-disabled gate evaluates an incomplete field set; the inline comment gives ORC-complex and v3-lineage triggers.
  • Scope and clarity: The patch is focused on metrics policy, transport, and tests. The remaining fix should keep the decision aligned with the exact writer schema/collector rather than widen unrelated code.
  • Concurrency and lifecycle: No new shared mutable state or lock-order risk. The per-writer flag is immutable after construction; mandatory commit-data fields are populated before the early return, and direct/merge/sorted-rollover paths preserve the flag.
  • Configuration and compatibility: Iceberg default/column/sort modes otherwise flow through MetricsConfig. The new optional Thrift fields are rolling-upgrade safe: unset old-FE payloads collect by default, while old BEs ignore the new field and continue collecting. No Doris dynamic configuration or storage-format compatibility change is introduced.
  • Parallel paths and FE/BE propagation: Direct table and merge sinks both set the field, merge forwards it into the inner table sink, and writer rollover reuses the same sink. That complete propagation is why the FE false negative suppresses both Parquet/ORC lineage metrics and the ORC complex-field case.
  • Transactions, persistence, and data writes: HasTableOperations correctly resolves v3 transaction metadata, and the helper uses the matching reserved lineage IDs/types. The change affects manifest metrics only; file contents, transaction atomicity, EditLog, and visible-version semantics are not otherwise changed.
  • Errors, observability, and performance: Missing/partial consumer maps and scan-close failures now return unknown rather than partial statistics. No new observability is needed. Skipping a guaranteed-unused ORC reopen is sound; the remaining per-file schema-index work is already covered by an existing performance thread and was not duplicated.
  • Tests: The new FE/BE unit tests cover primitive none/counts/truncate modes, repeated descendants, v3 type lookup, unknown statistics, close failure, disabled footer work, and old-FE default behavior. Coverage is missing for the two accepted false-negative triggers. Per the review-runner contract, I performed static review only and did not run builds or tests.
  • User focus: No additional user-provided focus was supplied.

Schema schema = table.schema();
MetricsConfig metricsConfig = MetricsConfig.forTable(table);
return TypeUtil.indexById(schema.asStruct()).values().stream()
.filter(field -> field.type().isPrimitiveType())

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] Evaluate collection against the actual writer field set

This gate can return false even though the writer has enabled metrics outside this primitive user-schema set. For ORC items list<int> with default none and column.items=counts, it drops the top-level items field and only checks items.element (still none), although both Doris and Iceberg ORC metrics publish top-level counts. Separately, for a v3 rewrite/merge with default counts and every user field overridden to none, this returns false before the binders append _row_id and _last_updated_sequence_number; those appended fields inherit counts, and the collectors/helper support their reserved IDs. In both cases BE skips the footer and requested manifest metrics disappear. Please evaluate the effective policy against the exact schema/field set sent to the selected writer (including v3 lineage and ORC top-level complex fields), with tests for both triggers.

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17630	4163	4210	4163
q2	2015	329	206	206
q3	10264	1431	832	832
q4	4690	474	338	338
q5	7520	869	586	586
q6	188	179	145	145
q7	780	814	611	611
q8	9349	1553	1535	1535
q9	5535	4367	4328	4328
q10	6752	1740	1475	1475
q11	499	372	325	325
q12	749	586	485	485
q13	18090	3339	2786	2786
q14	270	263	255	255
q15	q16	796	778	719	719
q17	1034	984	1076	984
q18	6913	5780	5599	5599
q19	1251	1238	1037	1037
q20	826	699	576	576
q21	5813	2590	2452	2452
q22	426	360	301	301
Total cold run time: 101390 ms
Total hot run time: 29738 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4471	4393	4403	4393
q2	286	321	218	218
q3	4568	4987	4414	4414
q4	2162	2233	1409	1409
q5	4404	4226	4308	4226
q6	231	177	134	134
q7	1729	1996	1752	1752
q8	2477	2225	2158	2158
q9	7885	7883	7735	7735
q10	4720	4654	4189	4189
q11	573	435	400	400
q12	761	766	568	568
q13	3466	3711	3030	3030
q14	299	319	302	302
q15	q16	736	744	698	698
q17	1351	1357	1298	1298
q18	7947	7513	7310	7310
q19	1130	1078	1061	1061
q20	2195	2280	1953	1953
q21	5337	4715	4539	4539
q22	515	455	415	415
Total cold run time: 57243 ms
Total hot run time: 52202 ms

@hello-stephen

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

query5	4339	622	493	493
query6	463	226	204	204
query7	4967	589	342	342
query8	351	196	175	175
query9	8760	4073	4048	4048
query10	478	365	301	301
query11	5916	2350	2154	2154
query12	161	104	105	104
query13	1282	629	435	435
query14	6226	5218	4870	4870
query14_1	4295	4247	4246	4246
query15	224	203	181	181
query16	1043	514	482	482
query17	1154	723	584	584
query18	2592	476	360	360
query19	216	194	155	155
query20	114	110	106	106
query21	239	161	138	138
query22	13642	13648	13395	13395
query23	17415	16522	16125	16125
query23_1	16268	16337	16162	16162
query24	7547	1764	1289	1289
query24_1	1317	1297	1305	1297
query25	568	463	406	406
query26	1368	378	206	206
query27	2542	612	380	380
query28	4437	1981	2005	1981
query29	1100	637	496	496
query30	338	265	236	236
query31	1111	1092	994	994
query32	112	72	61	61
query33	523	336	280	280
query34	1166	1147	627	627
query35	775	793	671	671
query36	1200	1174	1052	1052
query37	161	115	95	95
query38	1898	1715	1659	1659
query39	891	890	883	883
query39_1	838	841	881	841
query40	287	168	142	142
query41	65	63	65	63
query42	94	91	91	91
query43	324	329	276	276
query44	1393	789	764	764
query45	194	188	177	177
query46	1069	1216	722	722
query47	2185	2116	2038	2038
query48	402	431	301	301
query49	577	414	300	300
query50	1123	443	327	327
query51	10829	11187	10952	10952
query52	89	90	77	77
query53	259	280	210	210
query54	288	234	216	216
query55	74	72	67	67
query56	291	312	302	302
query57	1316	1293	1212	1212
query58	271	266	252	252
query59	1617	1605	1476	1476
query60	310	276	260	260
query61	153	161	153	153
query62	545	500	435	435
query63	248	209	203	203
query64	2819	1071	893	893
query65	4730	4664	4666	4664
query66	1790	505	383	383
query67	29440	29220	29011	29011
query68	3115	1594	951	951
query69	420	301	280	280
query70	1040	940	950	940
query71	366	343	310	310
query72	3029	2655	2352	2352
query73	838	729	409	409
query74	5026	4923	4712	4712
query75	2544	2513	2139	2139
query76	2324	1177	757	757
query77	353	376	278	278
query78	11868	11996	11444	11444
query79	2371	1138	802	802
query80	1591	550	469	469
query81	523	325	286	286
query82	588	157	123	123
query83	371	322	302	302
query84	287	163	129	129
query85	976	651	528	528
query86	420	303	279	279
query87	1822	1845	1764	1764
query88	3687	2852	2757	2757
query89	431	388	337	337
query90	1903	203	195	195
query91	205	193	169	169
query92	63	61	56	56
query93	1724	1531	951	951
query94	715	365	304	304
query95	785	598	475	475
query96	1124	878	348	348
query97	2646	2618	2479	2479
query98	215	207	200	200
query99	1097	1116	970	970
Total cold run time: 265729 ms
Total hot run time: 178142 ms

@hello-stephen

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

query1	0.00	0.00	0.01
query2	0.14	0.09	0.08
query3	0.37	0.25	0.25
query4	1.61	0.25	0.25
query5	0.33	0.32	0.32
query6	1.16	0.67	0.66
query7	0.04	0.01	0.01
query8	0.08	0.07	0.07
query9	0.53	0.39	0.38
query10	0.59	0.58	0.58
query11	0.32	0.20	0.18
query12	0.32	0.20	0.19
query13	0.54	0.54	0.54
query14	0.95	0.92	0.93
query15	0.68	0.61	0.60
query16	0.39	0.38	0.40
query17	1.04	1.03	0.99
query18	0.32	0.30	0.31
query19	1.95	1.79	1.84
query20	0.03	0.02	0.01
query21	15.41	0.40	0.33
query22	4.74	0.13	0.13
query23	15.81	0.50	0.30
query24	2.45	0.62	0.44
query25	0.15	0.11	0.11
query26	0.74	0.27	0.22
query27	0.10	0.09	0.10
query28	3.52	0.89	0.50
query29	12.45	4.36	3.37
query30	0.37	0.28	0.26
query31	2.79	0.63	0.34
query32	3.25	0.64	0.48
query33	2.97	2.99	2.94
query34	15.64	4.14	3.41
query35	3.30	3.26	3.28
query36	0.65	0.53	0.50
query37	0.14	0.10	0.09
query38	0.08	0.07	0.07
query39	0.08	0.05	0.06
query40	0.20	0.20	0.17
query41	0.13	0.08	0.09
query42	0.09	0.06	0.06
query43	0.08	0.07	0.07
Total cold run time: 96.53 s
Total hot run time: 25.77 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 87.01% (67/77) 🎉
Increment coverage report
Complete coverage report

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@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.62% (1908/2458)
Line Coverage 64.48% (34154/52966)
Region Coverage 64.91% (17574/27076)
Branch Coverage 54.05% (9417/17424)

@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: changes requested (three-round cap reached)

One new P1 regression remains on head 53a14e38c9155eefaa1207531f3c7b1d278fe39c: the added string-bound conversion can decode a numeric ORC bound that the pre-existing collector mislabeled after a complex field. With invalid UTF-8 bytes, FE throws during convertToWriterResult after BE has produced the file, so insert, rewrite, and merge can fail. The trigger and fix direction are inline.

Review completion: all three permitted rounds were completed. Both normal final passes returned NO_NEW_VALUABLE_FINDINGS, but the final risk pass produced this accepted candidate. The workflow forbids a fourth convergence round, so this review is explicitly incomplete at the round limit; every currently known candidate nevertheless has a verified, deduplicated main-agent conclusion.

Critical checkpoint conclusions:

  • Goal and proof: the aggregate diff otherwise applies Iceberg none, counts, truncate(N), and full policies to the correct metric families, handles repeated descendants and v3 lineage, skips disabled BE footer work, and makes missing read statistics unknown. The new cross-type ORC trigger means the goal is not yet correct for every writer schema, and no test covers it.
  • Scope and clarity: the patch is focused on metrics policy, propagation, footer skipping, and statistics fallback. All eight bundled prior inline concerns have corresponding fixes on the current head.
  • Concurrency and lifecycle: no new thread, lock, shared mutable state, static initialization, or ownership cycle is introduced. The per-writer flag is immutable; the disabled path retains file identity, counts, size, content, and partition data before skipping footer extraction.
  • Configuration and conditions: no Doris configuration item is added; existing Iceberg table properties drive the policy. The Parquet-leaf versus ORC-top-level condition matches the collectors' intended field sets, but the ORC collector's physical-ID assumption creates the accepted interaction.
  • Compatibility, parallel paths, and FE-BE state: the optional thrift flag is sent by direct and merge sinks, preserves presence through merge nesting, reaches normal/sorted/rolled writers, defaults to collection for old FE/new BE, and is safely ignored by old BE/new FE. Insert, rewrite, and merge all share the affected FE conversion.
  • Tests and results: unit coverage exercises modes, repeated ancestry, v3 lineage, disabled/unset collection, missing maps, and close failure, but lacks the nested-numeric-followed-by-string ORC case. Per the review contract, I ran no local build or tests. At submission, compile, Cloud UT, vault P0, format, and CheckStyle are green; macOS BE UT failed before compilation from the JDK 25 versus required JDK 17 runner mismatch; both coverage checks are red; main BE/FE UT and several regressions remain pending.
  • Observability and errors: existing transaction logging will expose the failure, but observability cannot make the deterministic conversion safe. The RuntimeIOException correctly fails rather than silently continuing.
  • Transactions, persistence, and data writes: no EditLog or durable Doris metadata schema changes are involved. Existing Iceberg transaction boundaries remain, but the accepted failure happens during manifest-metric conversion after the BE data file is written and before commit.
  • Performance: capturing schema/config once per batch and skipping unused footer extraction remove the intended fixed and remote-I/O work. Remaining per-file parent indexing is in the already-raised policy-construction performance family and was not duplicated.
  • Other issues: three serious adjacent ORC producer defects were independently validated—shifted physical IDs after complex fields, sub-millisecond timestamp upper bounds, and negative-decimal sign encoding—but their original same-type/timestamp/decimal behavior predates this aggregate diff and is unchanged or less exposed, so they are noted as non-blocking follow-up risks rather than charged to this PR.

User focus: no additional review focus was provided; the complete PR was reviewed.

private static ByteBuffer truncateBound(Type type, ByteBuffer value, int length, boolean lowerBound) {
switch (type.typeId()) {
case STRING:
String stringValue = Conversions.fromByteBuffer(type, value).toString();

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] Do not decode shifted ORC bounds as UTF-8

The ORC collector still indexes top-level fields as i + 1, so after a complex field it can attach a descendant's bytes to the following field. For s struct<a:int>, b string with s.a=-1, the second iteration reads a's integer statistics and stores eight 0xFF bytes under b's Iceberg ID. Before this diff those bytes were passed to Metrics without decoding; under the normal truncate(16) mode this new call decodes them as UTF-8, and Iceberg's strict decoder throws RuntimeIOException, causing insert/rewrite/merge to fail during FE commit conversion. Please resolve the actual ORC column ID before type-aware conversion (or otherwise guarantee the bound type matches the field), and cover a nested negative integer followed by a string in an ORC write test.

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17613	4107	4192	4107
q2	2012	319	197	197
q3	10368	1405	841	841
q4	4680	473	342	342
q5	7496	876	577	577
q6	195	172	136	136
q7	739	841	612	612
q8	9341	1463	1554	1463
q9	5592	4329	4356	4329
q10	6741	1735	1483	1483
q11	496	370	342	342
q12	718	581	461	461
q13	18099	3417	2728	2728
q14	274	265	250	250
q15	q16	786	772	875	772
q17	988	1017	987	987
q18	6873	5838	5576	5576
q19	1224	1224	1047	1047
q20	809	661	579	579
q21	5554	2634	2501	2501
q22	435	359	306	306
Total cold run time: 101033 ms
Total hot run time: 29636 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4484	4369	4350	4350
q2	285	333	226	226
q3	4572	4983	4377	4377
q4	2095	2180	1378	1378
q5	4407	4278	4245	4245
q6	227	184	128	128
q7	1732	1920	1890	1890
q8	2584	2237	2198	2198
q9	8052	8254	7893	7893
q10	4721	4693	4188	4188
q11	595	422	382	382
q12	754	789	558	558
q13	3416	3559	3028	3028
q14	296	314	280	280
q15	q16	744	734	625	625
q17	1369	1353	1335	1335
q18	7939	7338	7179	7179
q19	1181	1184	1101	1101
q20	2230	2217	1941	1941
q21	5318	4683	4531	4531
q22	528	460	413	413
Total cold run time: 57529 ms
Total hot run time: 52246 ms

@hello-stephen

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

query5	4325	626	485	485
query6	474	228	215	215
query7	4877	613	353	353
query8	337	188	166	166
query9	8783	4027	4110	4027
query10	448	360	303	303
query11	5938	2354	2121	2121
query12	153	102	104	102
query13	1267	598	453	453
query14	6780	5247	4893	4893
query14_1	4287	4246	4238	4238
query15	211	212	182	182
query16	1029	504	469	469
query17	1124	716	575	575
query18	2715	498	359	359
query19	219	200	149	149
query20	115	110	110	110
query21	237	160	140	140
query22	13604	13546	13250	13250
query23	17387	16448	16178	16178
query23_1	16286	16329	16286	16286
query24	7475	1763	1290	1290
query24_1	1305	1308	1285	1285
query25	563	468	399	399
query26	1361	358	214	214
query27	2555	584	367	367
query28	4418	2011	1998	1998
query29	1080	638	492	492
query30	348	263	228	228
query31	1133	1100	975	975
query32	120	62	63	62
query33	511	322	257	257
query34	1179	1097	651	651
query35	770	789	678	678
query36	1247	1217	1025	1025
query37	154	153	91	91
query38	1872	1692	1647	1647
query39	911	872	864	864
query39_1	862	830	834	830
query40	246	159	140	140
query41	66	69	64	64
query42	92	92	90	90
query43	322	330	279	279
query44	1419	782	768	768
query45	197	204	171	171
query46	1059	1174	724	724
query47	2077	2121	1980	1980
query48	408	411	285	285
query49	586	416	305	305
query50	1037	427	358	358
query51	11030	10745	11010	10745
query52	94	87	74	74
query53	259	280	206	206
query54	284	246	225	225
query55	81	70	65	65
query56	316	317	287	287
query57	1320	1284	1183	1183
query58	276	257	259	257
query59	1590	1655	1463	1463
query60	307	269	263	263
query61	155	146	147	146
query62	542	495	424	424
query63	250	207	205	205
query64	2775	1079	859	859
query65	4740	4653	4607	4607
query66	1783	519	384	384
query67	29291	29339	29041	29041
query68	3006	1535	943	943
query69	409	310	269	269
query70	1105	981	939	939
query71	387	337	304	304
query72	3073	2650	2390	2390
query73	845	737	434	434
query74	5090	4886	4693	4693
query75	2545	2499	2138	2138
query76	2344	1197	784	784
query77	347	361	270	270
query78	11950	11983	11243	11243
query79	1486	1113	792	792
query80	1308	556	463	463
query81	557	330	287	287
query82	588	160	124	124
query83	372	322	298	298
query84	293	160	132	132
query85	991	791	508	508
query86	437	296	279	279
query87	1826	1819	1756	1756
query88	3723	2795	2774	2774
query89	439	376	329	329
query90	1965	208	184	184
query91	204	186	166	166
query92	62	63	56	56
query93	1731	1590	955	955
query94	712	344	308	308
query95	822	596	480	480
query96	1050	809	363	363
query97	2633	2631	2501	2501
query98	210	207	202	202
query99	1095	1108	971	971
Total cold run time: 264724 ms
Total hot run time: 177572 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.10	0.06	0.05
query3	0.28	0.14	0.13
query4	1.61	0.14	0.15
query5	0.24	0.22	0.22
query6	1.25	1.06	1.05
query7	0.04	0.01	0.01
query8	0.06	0.04	0.03
query9	0.39	0.31	0.30
query10	0.53	0.56	0.54
query11	0.19	0.14	0.14
query12	0.18	0.14	0.14
query13	0.48	0.47	0.47
query14	1.05	1.01	1.01
query15	0.64	0.58	0.59
query16	0.32	0.32	0.33
query17	1.08	1.07	1.08
query18	0.22	0.21	0.22
query19	2.05	1.92	1.94
query20	0.02	0.02	0.01
query21	15.44	0.22	0.14
query22	4.78	0.05	0.05
query23	16.15	0.31	0.12
query24	2.95	0.42	0.32
query25	0.11	0.04	0.05
query26	0.73	0.20	0.16
query27	0.04	0.03	0.03
query28	3.54	0.91	0.54
query29	12.53	4.16	3.28
query30	0.28	0.15	0.14
query31	2.76	0.60	0.32
query32	3.22	0.59	0.48
query33	3.12	3.23	3.20
query34	15.40	4.26	3.52
query35	3.57	3.51	3.51
query36	0.56	0.47	0.43
query37	0.09	0.07	0.06
query38	0.04	0.04	0.04
query39	0.04	0.03	0.03
query40	0.17	0.16	0.16
query41	0.08	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.03	0.03
Total cold run time: 96.42 s
Total hot run time: 25.01 s

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

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.

Automated review conclusion for head 471470f5375d9483cd9b7034008fcedc8289f50b: one new blocking build issue remains; see the inline comment on vorc_transformer.cpp. The current head otherwise addresses all nine existing inline review concerns without a new semantic correctness finding.

Checkpoint conclusions:

  • Goal and proof: the FE metrics policy, BE collection gate, manifest normalization, ORC field-ID fix, and unavailable-statistics handling implement the stated behavior and have focused FE/BE tests, but the changed ORC collector currently fails compilation before those tests can run.
  • Scope: changes stay within Iceberg metrics collection/transport/filtering, ORC footer identity, and the Iceberg statistics consumer; no unrelated production behavior was found.
  • Concurrency and initialization: no new shared mutable state, locking, static initialization, or thread-lifecycle dependency is introduced.
  • Resource lifecycle: disabled collection skips footer work only after required commit metadata is populated; enabled close/reopen behavior is otherwise unchanged.
  • Configuration: no new runtime configuration item or validation boundary is introduced.
  • Compatibility and parallel paths: direct insert/overwrite, rewrite, merge, partition rollover, sorted writes, Parquet/ORC, and v1/v2/v3 schemas were traced. The optional Thrift field preserves the supported old-FE/new-BE default, and merge propagation is present. The supported upgrade order is BE first, then FE.
  • Tests: the added tests cover the policy flag/default, metric modes and truncation, repeated descendants, v3 lineage, checked close failure, and nested-ORC ID alignment. Local builds/tests were intentionally not run under the review contract; the authoritative compile job instead exposed the inline width-conversion failure.
  • Observability and failures: missing metrics fail closed to unknown statistics; no new silent partial result was found. Existing logging/error boundaries are retained.
  • Transactions, persistence, and data writes: transaction-local Iceberg metadata and v3 lineage schema resolution are consistent; no new EditLog, persistence, visibility, atomicity, or retry boundary is introduced.
  • Performance: the disabled gate avoids unnecessary footer work; the remaining fixed-schema-per-file work is already covered by an existing review thread and was not duplicated.
  • Other: all existing review threads were deduplicated before submission. No additional user-provided review focus was supplied.

Validation state at submission: CheckStyle, Clang Formatter, license, dependency, secret, large-file, and Cloud UT checks passed. TeamCity compile build 1000377 failed on the inline issue; BE/FE coverage checks then failed because that compile artifact was not published. The macOS BE UT failure is an independent runner JDK mismatch (JDK 25 versus required JDK 17). Remaining BE UT, FE UT, performance, and automated-review checks were still pending during this review. The local checkout lacks .worktree_initialized, thirdparty/installed, and protoc, so validation here was static plus exact-head CI-log inspection.

continue;
}
// ORC IDs are depth-first, so top-level fields after a complex field are not i + 1.
uint64_t orc_col_id = orc_root_type.getSubtype(i)->getColumnId();

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] Keep the ORC statistics index in the API's accepted width

This changes orc_col_id to uint64_t, but the next call passes it to orc::Statistics::getColumnStatistics(uint32_t). The compile job for this exact head fails here under Doris's -Werror,-Wshorten-64-to-32 flags (implicit conversion loses integer precision), so no compile artifact is produced and both coverage jobs fail downstream. Please perform an explicit, range-justified conversion (or otherwise keep the value in the API's accepted width) before the call.

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 75.00% (12/16) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 57.52% (23978/41688)
Line Coverage 41.26% (236023/572033)
Region Coverage 37.07% (186429/502957)
Branch Coverage 38.26% (83707/218792)

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 86.25% (69/80) 🎉
Increment coverage report
Complete coverage report

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17725	4101	4113	4101
q2	2002	332	194	194
q3	10296	1451	845	845
q4	4684	474	338	338
q5	7487	854	567	567
q6	184	172	138	138
q7	756	823	607	607
q8	9332	1653	1596	1596
q9	5586	4365	4381	4365
q10	6736	1737	1480	1480
q11	500	353	332	332
q12	729	579	456	456
q13	18096	3392	2766	2766
q14	268	257	229	229
q15	q16	787	784	713	713
q17	936	1044	990	990
q18	6905	5790	5555	5555
q19	1157	1269	1056	1056
q20	856	664	575	575
q21	5899	2880	2763	2763
q22	459	368	317	317
Total cold run time: 101380 ms
Total hot run time: 29983 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5189	4876	4834	4834
q2	288	332	211	211
q3	4953	5355	4719	4719
q4	2106	2142	1367	1367
q5	4999	4669	4622	4622
q6	240	180	128	128
q7	1904	1713	1548	1548
q8	2479	2148	2076	2076
q9	7625	7172	7215	7172
q10	4613	4605	4146	4146
q11	531	383	357	357
q12	735	744	530	530
q13	3063	3323	2778	2778
q14	279	285	258	258
q15	q16	673	706	604	604
q17	1298	1267	1244	1244
q18	7336	6887	6817	6817
q19	1116	1074	1084	1074
q20	2218	2217	1939	1939
q21	5280	4558	4517	4517
q22	522	459	413	413
Total cold run time: 57447 ms
Total hot run time: 51354 ms

@hello-stephen

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

query5	4328	636	479	479
query6	489	216	213	213
query7	4872	584	357	357
query8	328	186	176	176
query9	8780	4068	4042	4042
query10	477	340	294	294
query11	5905	2383	2141	2141
query12	155	100	99	99
query13	1278	558	420	420
query14	6407	5170	4851	4851
query14_1	4278	4216	4211	4211
query15	222	204	177	177
query16	1019	497	450	450
query17	1088	693	555	555
query18	2525	457	335	335
query19	204	184	142	142
query20	112	107	107	107
query21	232	160	130	130
query22	13546	13676	13325	13325
query23	17265	16461	16032	16032
query23_1	16097	16153	16253	16153
query24	7559	1757	1279	1279
query24_1	1312	1298	1303	1298
query25	560	467	397	397
query26	1362	388	228	228
query27	2557	579	390	390
query28	4482	1981	2007	1981
query29	1080	616	536	536
query30	339	261	222	222
query31	1110	1090	963	963
query32	110	62	63	62
query33	518	314	244	244
query34	1198	1127	644	644
query35	763	791	673	673
query36	1195	1182	1082	1082
query37	151	109	97	97
query38	1876	1704	1658	1658
query39	868	865	865	865
query39_1	836	837	840	837
query40	245	162	143	143
query41	63	69	66	66
query42	90	91	94	91
query43	320	320	284	284
query44	1411	772	761	761
query45	198	181	169	169
query46	1067	1175	692	692
query47	2136	2092	2064	2064
query48	381	414	296	296
query49	584	420	304	304
query50	1072	442	338	338
query51	11122	11032	10826	10826
query52	95	86	71	71
query53	265	276	206	206
query54	281	250	213	213
query55	76	76	69	69
query56	302	309	285	285
query57	1344	1304	1220	1220
query58	287	243	245	243
query59	1547	1632	1413	1413
query60	350	294	257	257
query61	153	153	159	153
query62	546	524	424	424
query63	246	212	196	196
query64	2802	1050	882	882
query65	4713	4597	4589	4589
query66	1848	512	366	366
query67	29249	29152	29025	29025
query68	3140	1574	1060	1060
query69	422	306	260	260
query70	1093	980	935	935
query71	378	337	340	337
query72	3071	2680	2536	2536
query73	848	800	451	451
query74	5058	4929	4771	4771
query75	2551	2502	2150	2150
query76	2333	1192	795	795
query77	363	398	304	304
query78	11931	11894	11336	11336
query79	1363	1164	737	737
query80	663	573	488	488
query81	475	342	306	306
query82	562	164	122	122
query83	414	331	310	310
query84	279	171	143	143
query85	996	705	544	544
query86	352	295	278	278
query87	1818	1822	1758	1758
query88	3693	2788	2802	2788
query89	436	373	337	337
query90	1902	204	192	192
query91	208	201	163	163
query92	63	64	54	54
query93	1597	1672	982	982
query94	563	346	309	309
query95	768	485	476	476
query96	1002	809	366	366
query97	2629	2616	2492	2492
query98	209	206	203	203
query99	1098	1110	1003	1003
Total cold run time: 263025 ms
Total hot run time: 177857 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.09	0.05	0.05
query3	0.25	0.14	0.14
query4	1.62	0.14	0.14
query5	0.24	0.23	0.22
query6	1.24	1.11	1.04
query7	0.04	0.01	0.01
query8	0.06	0.03	0.03
query9	0.38	0.32	0.32
query10	0.56	0.55	0.54
query11	0.21	0.15	0.14
query12	0.20	0.14	0.15
query13	0.45	0.47	0.48
query14	1.01	1.02	1.01
query15	0.59	0.59	0.60
query16	0.32	0.34	0.32
query17	1.09	1.12	1.08
query18	0.23	0.21	0.22
query19	2.09	1.90	1.93
query20	0.02	0.02	0.01
query21	15.43	0.20	0.15
query22	4.99	0.05	0.05
query23	16.15	0.30	0.12
query24	2.99	0.43	0.34
query25	0.13	0.04	0.04
query26	0.71	0.20	0.15
query27	0.05	0.04	0.03
query28	3.57	0.91	0.55
query29	12.49	4.07	3.28
query30	0.28	0.15	0.16
query31	2.76	0.61	0.31
query32	3.23	0.59	0.49
query33	3.17	3.15	3.12
query34	15.46	4.21	3.48
query35	3.53	3.51	3.49
query36	0.55	0.43	0.43
query37	0.09	0.07	0.07
query38	0.05	0.04	0.04
query39	0.04	0.04	0.03
query40	0.17	0.18	0.17
query41	0.08	0.03	0.04
query42	0.04	0.03	0.03
query43	0.04	0.04	0.04
Total cold run time: 96.7 s
Total hot run time: 24.96 s

@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.62% (1908/2458)
Line Coverage 64.47% (34148/52966)
Region Coverage 64.90% (17572/27076)
Branch Coverage 54.03% (9415/17424)

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

One correctness issue remains in ORC truncate-mode metric handling; see the inline comment.

  • Goal and proof: The change now honors Iceberg metrics modes across FE filtering and BE footer collection, including disabled collection, counts/truncate behavior, repeated fields, v3 lineage, ORC IDs, and missing statistics. The added FE/BE unit cases cover those repaired paths, but not the accepted ORC no-successor edge case.
  • Scope and clarity: The changes are focused on the required FE, BE, Thrift, statistics-consumer, and test boundaries and reuse Iceberg's policy/type utilities.
  • Concurrency and lifecycle: No new shared mutable concurrency or lock ordering is introduced. Writer close/footer ordering is preserved; disabling metrics skips only optional footer extraction, including the ORC reopen. No static-initialization or ownership issue was found.
  • Configuration, compatibility, and parallel paths: Existing Iceberg table properties remain the source of policy. The optional Thrift flag defaults to collection when absent, preserving rolling upgrades. Normal insert, rewrite, and merge paths propagate it, and v3 writer lineage is handled consistently.
  • Conditions and data correctness: Missing file metrics remain unknown rather than becoming partial or fabricated statistics. Commit atomicity and persisted table formats are unchanged. The one remaining gap is the ORC-specific upper-bound fallback described inline.
  • FE/BE propagation and observability: The flag crosses both table and merge sinks into every partition writer. No additional logs or runtime metrics are needed for this policy-only behavior.
  • Performance: Disabled collection avoids unused serialization/footer work. Remaining repeated schema indexing is already covered by an existing review thread, so it was not duplicated.
  • Tests and results: Full compile, CheckStyle, both clang-format checks, and vault_p0 pass. I did not run builds or tests locally under the supplied review contract. The current FE UT failure is a truncated dependency download and the macOS BE job stops on a runner JDK mismatch before relevant tests; several other suites are still pending.
  • Other issues: After three convergence rounds, all other suspicious points were either dismissed with code evidence or deduplicated against existing threads.

User focus: No additional focus points were supplied; the complete PR was reviewed.

String stringValue = Conversions.fromByteBuffer(type, value).toString();
String truncatedString = lowerBound
? UnicodeUtil.truncateStringMin(stringValue, length)
: UnicodeUtil.truncateStringMax(stringValue, length);

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] Preserve ORC's no-successor upper-bound fallback

This shared helper now applies the Parquet null result to ORC as well. For an ORC string maximum whose first retained code point is U+10FFFF (for example U+10FFFF followed by another character with truncate(1)), UnicodeUtil.truncateStringMax cannot increment the prefix and returns null, so filterBounds drops the upper bound. Iceberg 1.10.1's ORC path deliberately falls back to the original full maximum in this case, unlike its Parquet path; otherwise ORC manifests lose the requested upper metric and pruning/readable-metrics information. Please pass the file format into the bound filtering and retain the original ORC upper string value when no safe truncated successor exists, with an ORC-backed edge test. This is distinct from the prior thread about not truncating bounds at all: it is the ORC-only fallback lost by the new unified fix.

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 88.89% (16/18) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 74.97% (30488/40666)
Line Coverage 59.11% (336058/568515)
Region Coverage 55.77% (281534/504849)
Branch Coverage 57.19% (125211/218934)

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