Skip to content

[fix](iceberg) Derive count pushdown from live manifests - #66778

Open
Gabriel39 wants to merge 4 commits into
apache:masterfrom
Gabriel39:fix/iceberg-count-manifest-records
Open

[fix](iceberg) Derive count pushdown from live manifests#66778
Gabriel39 wants to merge 4 commits into
apache:masterfrom
Gabriel39:fix/iceberg-count-manifest-records

Conversation

@Gabriel39

@Gabriel39 Gabriel39 commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: None

Problem Summary:

Iceberg V2 COUNT(*) pushdown treated the optional total-records snapshot summary field as an exact query result. A writer can provide a syntactically valid positive value that does not match the live data files, causing Doris to return a wrong count without reading data.

This change derives an exact unfiltered count by summing addedRowsCount + existingRowsCount across the current manifest list. The common path is O(manifests) and reads only the first live data-file task to build the representative range. Older manifest lists that omit aggregate counters fall back to bounded per-file recordCount enumeration. Queries with row filters or live delete files use the normal scan, while invalid counters and overflow safely fall back instead of exposing unverified metadata.

Release note

Fix incorrect Iceberg V2 COUNT(*) results when snapshot summary row counts are inaccurate.

Check List (For Author)

  • Test: Unit Test
    • IcebergScanPlanProviderTest: 148 tests passed
  • FE Checkstyle: passed with 0 violations
  • Behavior changed: Yes. Exact unfiltered COUNT(*) pushdown now uses current manifest-list aggregates and safely falls back when exactness cannot be proven.
  • Does this need documentation: No

Iceberg snapshot summary fields are optional writer metadata and may contain a valid but incorrect positive row count. Derive exact unfiltered COUNT(*) results from live data-file record counts, and fall back to a normal scan for filters, deletes, invalid counts, or overflow.

Tests: IcebergScanPlanProviderTest (148 tests)
@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

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: 17607 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 13c403300e05480e2064535357aaca5639c31f87, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17583	3060	3009	3009
q2	1948	304	164	164
q3	10328	888	514	514
q4	4669	252	200	200
q5	7680	575	378	378
q6	141	119	95	95
q7	541	524	398	398
q8	9250	953	867	867
q9	3414	2389	2329	2329
q10	6523	874	730	730
q11	447	261	248	248
q12	704	380	331	331
q13	17889	1878	1535	1535
q14	163	155	145	145
q15	q16	448	406	359	359
q17	806	845	798	798
q18	3141	2269	2239	2239
q19	1247	936	842	842
q20	643	522	430	430
q21	5652	1749	1847	1749
q22	332	284	247	247
Total cold run time: 93549 ms
Total hot run time: 17607 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3409	3347	3341	3341
q2	206	220	156	156
q3	2214	2284	2124	2124
q4	1209	1184	903	903
q5	2185	2130	2117	2117
q6	184	120	89	89
q7	1096	964	869	869
q8	1627	1415	1414	1414
q9	3089	3105	3060	3060
q10	1882	1785	1640	1640
q11	355	280	255	255
q12	474	441	337	337
q13	1855	1845	1571	1571
q14	168	179	166	166
q15	q16	409	414	355	355
q17	1039	1039	1031	1031
q18	4960	4437	4823	4437
q19	865	834	868	834
q20	981	947	831	831
q21	3850	3232	3245	3232
q22	539	351	334	334
Total cold run time: 32596 ms
Total hot run time: 29096 ms

Use current manifest-list live-row aggregates for the common no-delete path and read only one representative file task. Fall back to bounded per-file counting when old manifests omit aggregates, and to a normal scan when live delete manifests are present.

Tests: IcebergScanPlanProviderTest (148 tests)
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

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

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

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17565	3066	3085	3066
q2	1897	237	151	151
q3	10472	868	515	515
q4	4675	241	195	195
q5	7687	571	393	393
q6	138	117	96	96
q7	535	519	392	392
q8	10050	925	915	915
q9	4507	2366	2369	2366
q10	6579	853	729	729
q11	447	265	252	252
q12	761	386	328	328
q13	17889	1833	1551	1551
q14	163	154	140	140
q15	q16	446	407	361	361
q17	853	782	809	782
q18	3141	2261	2277	2261
q19	1121	962	827	827
q20	652	560	455	455
q21	5436	1764	1964	1764
q22	337	280	241	241
Total cold run time: 95351 ms
Total hot run time: 17780 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3413	3386	3354	3354
q2	212	223	157	157
q3	2281	2344	2157	2157
q4	1197	1166	896	896
q5	2176	2113	2143	2113
q6	181	118	89	89
q7	1040	935	850	850
q8	1627	1430	1424	1424
q9	3111	3098	3059	3059
q10	1866	1764	1626	1626
q11	353	275	256	256
q12	470	439	340	340
q13	1806	1853	1543	1543
q14	181	172	156	156
q15	q16	398	399	357	357
q17	1062	1044	1039	1039
q18	4949	4413	4743	4413
q19	891	868	895	868
q20	953	947	794	794
q21	3544	2970	3104	2970
q22	400	335	331	331
Total cold run time: 32111 ms
Total hot run time: 28792 ms

@hello-stephen

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

query5	3167	418	384	384
query6	449	167	147	147
query7	4825	426	261	261
query8	294	116	118	116
query9	8617	2921	2927	2921
query10	383	258	212	212
query11	5400	1048	915	915
query12	123	73	72	72
query13	1191	455	330	330
query14	4641	2019	1877	1877
query14_1	1802	1783	1793	1783
query15	135	118	113	113
query16	822	382	340	340
query17	743	471	376	376
query18	2118	345	245	245
query19	173	142	119	119
query20	73	71	71	71
query21	168	118	104	104
query22	5216	5300	5329	5300
query23	7422	6649	6421	6421
query23_1	6614	6751	6597	6597
query24	7234	1101	785	785
query24_1	769	798	801	798
query25	391	313	266	266
query26	1184	274	170	170
query27	2688	456	288	288
query28	4640	1544	1522	1522
query29	685	480	366	366
query30	294	176	147	147
query31	899	665	609	609
query32	61	53	49	49
query33	373	217	184	184
query34	979	799	491	491
query35	409	402	345	345
query36	552	547	529	529
query37	123	88	77	77
query38	861	847	802	802
query39	536	544	540	540
query39_1	510	532	529	529
query40	221	134	112	112
query41	59	57	56	56
query42	78	75	75	75
query43	248	250	217	217
query44	1034	574	571	571
query45	115	111	105	105
query46	823	858	518	518
query47	984	955	953	953
query48	328	340	242	242
query49	638	252	194	194
query50	852	373	263	263
query51	8308	8436	8245	8245
query52	69	68	65	65
query53	198	212	159	159
query54	223	176	182	176
query55	69	56	51	51
query56	219	227	198	198
query57	623	614	543	543
query58	204	199	193	193
query59	1085	1063	951	951
query60	213	196	186	186
query61	108	104	106	104
query62	330	197	171	171
query63	181	154	154	154
query64	2232	663	561	561
query65	1566	1491	1489	1489
query66	1869	297	246	246
query67	9688	9873	9744	9744
query68	2951	1251	818	818
query69	359	226	206	206
query70	690	600	568	568
query71	295	257	240	240
query72	2350	1749	1588	1588
query73	669	591	342	342
query74	1966	1218	1143	1143
query75	1210	1158	1008	1008
query76	2381	740	551	551
query77	241	246	199	199
query78	5400	4798	4678	4678
query79	1252	835	570	570
query80	1295	390	339	339
query81	482	191	176	176
query82	644	139	107	107
query83	343	255	232	232
query84	312	123	102	102
query85	878	432	390	390
query86	393	176	164	164
query87	1149	977	895	895
query88	2788	2135	2150	2135
query89	321	232	208	208
query90	1961	148	137	137
query91	155	146	127	127
query92	52	48	46	46
query93	1362	1231	810	810
query94	647	239	215	215
query95	591	378	394	378
query96	869	609	278	278
query97	1108	1128	1046	1046
query98	148	133	135	133
query99	445	343	302	302
Total cold run time: 168402 ms
Total hot run time: 85964 ms

@hello-stephen

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

query1	0.01	0.00	0.01
query2	0.08	0.04	0.03
query3	0.24	0.12	0.11
query4	1.60	0.10	0.09
query5	0.17	0.16	0.17
query6	1.25	0.58	0.59
query7	0.03	0.00	0.01
query8	0.05	0.03	0.04
query9	0.30	0.21	0.21
query10	0.32	0.35	0.35
query11	0.15	0.11	0.11
query12	0.15	0.12	0.12
query13	0.30	0.31	0.32
query14	0.45	0.46	0.45
query15	0.37	0.34	0.35
query16	0.24	0.21	0.22
query17	0.70	0.72	0.69
query18	0.18	0.17	0.18
query19	1.13	1.17	1.20
query20	0.02	0.01	0.01
query21	15.44	0.16	0.12
query22	5.06	0.04	0.04
query23	16.20	0.26	0.10
query24	3.02	0.32	0.27
query25	0.11	0.04	0.03
query26	0.73	0.16	0.12
query27	0.03	0.03	0.03
query28	3.61	0.62	0.26
query29	12.43	3.14	2.55
query30	0.25	0.11	0.13
query31	2.76	0.37	0.17
query32	3.50	0.33	0.22
query33	1.55	1.51	1.60
query34	15.37	2.20	1.79
query35	1.74	1.72	1.73
query36	0.47	0.30	0.29
query37	0.06	0.04	0.04
query38	0.05	0.03	0.03
query39	0.03	0.02	0.02
query40	0.12	0.08	0.07
query41	0.07	0.02	0.02
query42	0.03	0.02	0.03
query43	0.03	0.03	0.03
Total cold run time: 90.4 s
Total hot run time: 14.7 s

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review status: complete/converged after three rounds. Every final-round reviewer returned NO_NEW_VALUABLE_FINDINGS, and every ledger candidate is resolved.

The central change is sound for its intended exactness boundary: an unfiltered, pinned Iceberg snapshot with no live delete files can derive its row total from live manifest-list counters, while missing, invalid, or overflowing metadata falls back conservatively. Three blocking regressions remain, each called out inline:

  1. Delete-bearing counts lose the existing lazy/backpressured planning path and can synchronously materialize a very large scan.
  2. ignore_iceberg_dangling_delete becomes inert without retiring its public contract or updating the unchanged P0 behavior check.
  3. The new old-manifest per-file fallback lets a lazy manifest-cache failure escape instead of recording it and retrying through the SDK.

Checkpoint conclusions: the source scope is localized and adds no new shared state, lock, lifecycle, persistence, transaction, write, SPI, thrift, or storage-format surface. Current/snapshot/ref pins, filters and partition pruning, COUNT argument semantics, format v1-v3 metadata, delete types, empty/zero/overflow cases, cache/SDK and sync/stream paths, representative-range handling, and both BE count carriers were reviewed. Compatibility cleanup is incomplete only as described inline; error handling is conservative except for the lazy-cache retry gap; no additional observability issue was found.

Tests were not run because the authoritative review bundle forbids builds and test execution. Static review covered all four changed files, the replacement/deleted unit tests, and the relevant unchanged external P0 assertions.

@Gabriel39
Gabriel39 requested a review from morrySnow as a code owner August 14, 2026 11:59
@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: 17545 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 79644f90de9df6473e16b8498fe06b7061b8fe74, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17556	3088	3113	3088
q2	1872	233	149	149
q3	10487	858	511	511
q4	4669	250	196	196
q5	7687	570	376	376
q6	136	114	91	91
q7	516	509	397	397
q8	9262	929	975	929
q9	3451	2383	2370	2370
q10	6523	850	695	695
q11	445	264	231	231
q12	699	392	319	319
q13	17870	1872	1525	1525
q14	160	155	138	138
q15	q16	441	401	362	362
q17	764	807	751	751
q18	3105	2275	2243	2243
q19	1267	895	746	746
q20	640	528	478	478
q21	5677	1709	1985	1709
q22	340	275	241	241
Total cold run time: 93567 ms
Total hot run time: 17545 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3483	3438	3364	3364
q2	210	218	154	154
q3	2302	2380	2159	2159
q4	1202	1169	894	894
q5	2180	2125	2115	2115
q6	173	119	88	88
q7	1023	910	870	870
q8	1607	1413	1417	1413
q9	3094	3078	3052	3052
q10	1865	1796	1624	1624
q11	351	273	255	255
q12	459	439	344	344
q13	1831	1889	1519	1519
q14	172	168	177	168
q15	q16	392	401	352	352
q17	1044	1047	1041	1041
q18	4941	4428	4776	4428
q19	866	832	854	832
q20	982	935	817	817
q21	3954	3212	3297	3212
q22	481	357	323	323
Total cold run time: 32612 ms
Total hot run time: 29024 ms

@hello-stephen

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

query5	4242	399	353	353
query6	395	161	152	152
query7	4887	416	258	258
query8	300	117	109	109
query9	8694	2947	2926	2926
query10	447	263	218	218
query11	5386	1052	947	947
query12	121	73	70	70
query13	1187	439	326	326
query14	5952	2002	1873	1873
query14_1	1797	1772	1780	1772
query15	173	122	116	116
query16	928	384	385	384
query17	808	466	382	382
query18	2336	367	244	244
query19	173	142	119	119
query20	72	72	70	70
query21	212	119	103	103
query22	5266	5286	5178	5178
query23	7288	6717	6618	6618
query23_1	6661	6749	6532	6532
query24	7326	1088	780	780
query24_1	813	787	792	787
query25	438	316	279	279
query26	1255	257	168	168
query27	2721	477	286	286
query28	4622	1527	1516	1516
query29	936	455	358	358
query30	276	177	154	154
query31	968	667	621	621
query32	106	51	51	51
query33	463	217	184	184
query34	1010	834	498	498
query35	408	414	338	338
query36	550	550	510	510
query37	127	89	75	75
query38	1019	840	795	795
query39	525	516	510	510
query39_1	519	546	541	541
query40	223	127	116	116
query41	59	59	57	57
query42	76	75	73	73
query43	251	251	223	223
query44	1018	578	575	575
query45	113	109	102	102
query46	795	859	534	534
query47	1010	975	997	975
query48	307	327	234	234
query49	539	239	204	204
query50	792	322	256	256
query51	8179	8139	8073	8073
query52	71	70	60	60
query53	215	213	154	154
query54	232	175	171	171
query55	81	56	56	56
query56	219	213	218	213
query57	656	623	659	623
query58	221	192	192	192
query59	1129	1138	1055	1055
query60	241	205	195	195
query61	128	133	117	117
query62	374	201	171	171
query63	185	157	152	152
query64	2609	675	546	546
query65	1580	1541	1539	1539
query66	1796	293	220	220
query67	9596	9557	9784	9557
query68	2946	1184	800	800
query69	353	226	196	196
query70	630	606	608	606
query71	288	247	248	247
query72	2311	1778	1578	1578
query73	606	596	337	337
query74	1981	1219	1142	1142
query75	1230	1153	995	995
query76	2295	747	528	528
query77	253	258	211	211
query78	5176	4787	4525	4525
query79	1264	867	589	589
query80	1174	375	336	336
query81	482	200	168	168
query82	633	141	107	107
query83	324	246	245	245
query84	310	120	100	100
query85	833	451	371	371
query86	391	202	169	169
query87	1014	974	876	876
query88	2847	2138	2124	2124
query89	309	235	210	210
query90	1958	136	137	136
query91	152	146	125	125
query92	52	47	44	44
query93	1411	1219	737	737
query94	632	258	227	227
query95	612	365	358	358
query96	821	617	273	273
query97	1088	1082	1062	1062
query98	162	137	133	133
query99	416	346	301	301
Total cold run time: 178487 ms
Total hot run time: 85574 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.

Request changes: one new P1 is attached, and the existing dangling-delete P1 remains unresolved.

Blocking findings:

  • Existing discussion #66778 (comment) already owns the ignore_iceberg_dangling_delete/P0 contract, so I am not duplicating it inline. The reply makes the flag active, but now pushes raw data-manifest rows for every position delete. The removed behavior and unchanged P0 require data rows minus position-delete rows; the changed 10-row/3-delete unit expectation of 10 therefore still violates the contract and the P0's expected pushed count of 1 remains broken.
  • The attached inline is a distinct cache-availability regression: snapshots with usable manifest aggregates but unusable old summary counters newly enter the representative fast path, where a lazy cache read can escape without failure accounting or a fresh SDK retry.

Critical checkpoint conclusions:

  • Goal and data correctness: deriving exact unfiltered COUNT from the pinned snapshot's live manifest/file metadata avoids the stale-summary bug for valid metadata, but the two P1 paths above mean the PR does not yet fully accomplish its goal.
  • Scope and clarity: the production change is focused on Iceberg COUNT planning and related comments/tests; no unrelated source changes were found.
  • Concurrency: this planning path and its count/cache-stat decisions run on the FE planning thread. The PR adds no thread, lock, lock ordering, or new shared mutable state.
  • Lifecycle and error handling: try-with-resources owns the scan iterables. The old-metadata consumer now discards partial state and retries correctly, but the aggregate representative consumer lacks the equivalent lazy-failure/close boundary described inline.
  • Configuration: no new configuration item is added. The existing session variable is dynamically read as before, but its flag-true numeric semantics are not preserved, as covered by the existing thread.
  • Compatibility: no function symbol, storage format, persistence format, or new FE/BE protocol field is introduced. The established -1 versus nonnegative table_level_row_count carrier remains compatible; the user-visible session-variable behavior is the compatibility regression.
  • Parallel paths and conditions: current and old manifest metadata, cache and SDK enumeration, filtered counts, equality/position deletes, v2/v3, snapshot pins, empty/zero-row cases, and synchronous/streaming planning were checked. The conditions otherwise fail closed or retain the normal delete-applying path; no third issue was substantiated.
  • Test coverage and results: units cover wrong summaries, pins, filters, deletes, empty tables, representative selection, and late old-metadata cache failure. The flag-true expected result is incorrect, and there is no aggregate-present/unusable-summary fail-on-first-manifest cache test. No build or test command was run because the review harness explicitly prohibits builds.
  • Observability: the repaired old-metadata fallback warns and records cache failure before retrying; the newly reachable aggregate path omits both on a lazy failure.
  • Transactions, persistence, and data writes: not applicable; this PR changes read planning only.
  • FE/BE handoff: no new variable is passed. Both Iceberg native reader paths retain the same nonnegative count shortcut and normal ranges retain -1.
  • Performance and remaining issues: current metadata stays O(manifests) plus one representative, old metadata is bounded-memory O(files), and streaming remains the large-scan memory fence. No additional correctness, lifecycle, compatibility, or performance issue remained after the final sweep.
  • User focus and completion: no additional user-provided focus was supplied, so the full PR was reviewed. The review converged after Round 2 with all candidates accepted, duplicate-suppressed, or dismissed; it is complete rather than capped.

@hello-stephen

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

query1	0.01	0.01	0.00
query2	0.07	0.03	0.03
query3	0.23	0.11	0.11
query4	1.61	0.10	0.11
query5	0.16	0.15	0.16
query6	1.25	0.60	0.64
query7	0.04	0.01	0.00
query8	0.05	0.03	0.03
query9	0.29	0.21	0.22
query10	0.35	0.34	0.35
query11	0.15	0.12	0.11
query12	0.14	0.11	0.11
query13	0.33	0.30	0.30
query14	0.46	0.44	0.46
query15	0.36	0.34	0.36
query16	0.23	0.23	0.22
query17	0.70	0.66	0.75
query18	0.18	0.16	0.15
query19	1.26	1.24	1.23
query20	0.01	0.02	0.02
query21	15.45	0.17	0.12
query22	5.08	0.04	0.04
query23	16.20	0.26	0.10
query24	3.01	0.34	0.25
query25	0.12	0.04	0.03
query26	0.77	0.17	0.12
query27	0.04	0.02	0.02
query28	3.66	0.53	0.27
query29	12.51	3.15	2.56
query30	0.26	0.12	0.12
query31	2.76	0.37	0.17
query32	3.53	0.31	0.22
query33	1.37	1.46	1.36
query34	15.44	2.22	1.80
query35	1.73	1.70	1.75
query36	0.45	0.29	0.28
query37	0.07	0.03	0.03
query38	0.05	0.03	0.03
query39	0.03	0.03	0.02
query40	0.11	0.08	0.07
query41	0.08	0.03	0.02
query42	0.03	0.02	0.02
query43	0.03	0.03	0.03
Total cold run time: 90.66 s
Total hot run time: 14.53 s

@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: 17601 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 12476576e1d6c52de872d143bb9080fdcdb13c1d, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17565	3028	3048	3028
q2	1880	230	147	147
q3	10491	861	505	505
q4	4670	251	196	196
q5	7677	564	379	379
q6	132	118	91	91
q7	539	518	391	391
q8	9263	880	997	880
q9	3406	2374	2344	2344
q10	6518	854	770	770
q11	458	249	238	238
q12	688	386	318	318
q13	17881	1940	1545	1545
q14	169	157	136	136
q15	q16	455	396	361	361
q17	822	808	738	738
q18	3068	2265	2231	2231
q19	1109	932	777	777
q20	651	513	459	459
q21	5322	1836	1924	1836
q22	336	270	231	231
Total cold run time: 93100 ms
Total hot run time: 17601 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3409	3337	3297	3297
q2	209	214	154	154
q3	2226	2324	2153	2153
q4	1187	1162	890	890
q5	2204	2122	2119	2119
q6	173	121	86	86
q7	1029	902	872	872
q8	1618	1384	1399	1384
q9	3076	3070	3029	3029
q10	1829	1789	1611	1611
q11	359	268	244	244
q12	458	435	348	348
q13	1811	1863	1534	1534
q14	170	172	157	157
q15	q16	388	398	355	355
q17	1033	1035	1013	1013
q18	4918	4391	4769	4391
q19	877	852	858	852
q20	967	943	818	818
q21	3774	3140	3251	3140
q22	404	359	344	344
Total cold run time: 32119 ms
Total hot run time: 28791 ms

@hello-stephen

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

query5	4236	412	329	329
query6	411	156	159	156
query7	4867	461	277	277
query8	294	123	111	111
query9	8673	2920	2913	2913
query10	423	281	217	217
query11	5384	1033	919	919
query12	113	74	71	71
query13	1205	467	353	353
query14	5962	1991	1859	1859
query14_1	1780	1745	1724	1724
query15	173	116	112	112
query16	915	383	351	351
query17	801	461	395	395
query18	2325	329	227	227
query19	161	142	105	105
query20	83	66	69	66
query21	208	115	100	100
query22	5356	5169	5201	5169
query23	7268	6594	6406	6406
query23_1	6724	6678	6472	6472
query24	7265	1126	785	785
query24_1	778	800	785	785
query25	414	280	234	234
query26	1244	252	159	159
query27	2735	445	290	290
query28	4671	1483	1523	1483
query29	928	440	339	339
query30	273	174	147	147
query31	974	663	607	607
query32	101	49	49	49
query33	444	228	163	163
query34	1006	826	485	485
query35	407	401	331	331
query36	540	555	512	512
query37	121	84	71	71
query38	1006	834	815	815
query39	532	524	523	523
query39_1	536	524	530	524
query40	217	116	110	110
query41	53	51	53	51
query42	75	75	73	73
query43	250	246	220	220
query44	1032	585	577	577
query45	111	110	102	102
query46	779	824	545	545
query47	931	972	956	956
query48	320	313	227	227
query49	534	234	189	189
query50	833	324	255	255
query51	8213	8268	8034	8034
query52	67	74	60	60
query53	219	213	159	159
query54	228	209	192	192
query55	67	56	59	56
query56	242	235	233	233
query57	661	631	604	604
query58	226	211	187	187
query59	1118	1134	996	996
query60	279	202	201	201
query61	141	136	141	136
query62	342	205	182	182
query63	185	157	161	157
query64	2835	762	677	677
query65	1592	1556	1542	1542
query66	1793	285	235	235
query67	9821	9677	9637	9637
query68	3030	1131	792	792
query69	350	220	190	190
query70	659	610	599	599
query71	283	263	237	237
query72	2353	1804	1592	1592
query73	631	631	339	339
query74	2000	1216	1131	1131
query75	1242	1145	987	987
query76	2384	748	581	581
query77	254	253	191	191
query78	5177	4809	4414	4414
query79	1182	840	576	576
query80	1201	379	333	333
query81	482	191	166	166
query82	642	137	112	112
query83	321	251	244	244
query84	305	121	98	98
query85	850	444	373	373
query86	389	172	165	165
query87	1031	960	881	881
query88	2828	2157	2158	2157
query89	315	231	199	199
query90	1882	143	151	143
query91	158	142	125	125
query92	51	50	47	47
query93	1392	1106	775	775
query94	661	251	220	220
query95	639	368	333	333
query96	800	615	293	293
query97	1102	1102	1076	1076
query98	155	133	130	130
query99	415	343	303	303
Total cold run time: 179116 ms
Total hot run time: 85111 ms

@hello-stephen

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

query1	0.00	0.01	0.00
query2	0.08	0.04	0.04
query3	0.24	0.11	0.10
query4	1.60	0.10	0.09
query5	0.17	0.16	0.17
query6	1.26	0.64	0.61
query7	0.03	0.01	0.01
query8	0.05	0.03	0.03
query9	0.29	0.20	0.22
query10	0.36	0.34	0.35
query11	0.16	0.11	0.11
query12	0.14	0.11	0.11
query13	0.32	0.31	0.30
query14	0.45	0.45	0.46
query15	0.36	0.34	0.34
query16	0.23	0.24	0.21
query17	0.74	0.73	0.70
query18	0.18	0.17	0.16
query19	1.20	1.19	1.20
query20	0.01	0.01	0.01
query21	15.45	0.16	0.11
query22	5.08	0.05	0.05
query23	16.18	0.26	0.10
query24	2.95	0.32	0.25
query25	0.10	0.04	0.03
query26	0.82	0.17	0.13
query27	0.04	0.03	0.04
query28	3.65	0.56	0.27
query29	12.54	3.18	2.56
query30	0.25	0.12	0.12
query31	2.77	0.36	0.17
query32	3.56	0.32	0.21
query33	1.36	1.39	1.53
query34	15.36	2.18	1.74
query35	1.73	1.76	1.74
query36	0.46	0.28	0.29
query37	0.06	0.04	0.04
query38	0.04	0.03	0.03
query39	0.03	0.02	0.02
query40	0.12	0.08	0.07
query41	0.08	0.03	0.02
query42	0.03	0.02	0.02
query43	0.03	0.02	0.03
Total cold run time: 90.56 s
Total hot run time: 14.56 s

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review status: capped/incomplete (3 of 3 rounds; a valuable candidate surfaced in the final round).

Summary opinion

The PR fixes the core exactness problem in the right direction: exact unfiltered COUNT(*) results now come from live manifest state instead of optional snapshot-summary values, and unprovable states fall back to row scanning. I found no new result-correctness blocker distinct from the existing review threads. I am requesting changes for two avoidable full delete-manifest rescans on the successful position-delete compatibility path; both are reported inline.

Critical checkpoint conclusions

  • Goal and proof: The implementation accomplishes the stated goal for the reviewed paths. Manifest-list ADDED/EXISTING row totals or the live-file fallback provide the data-row proof; equality deletes, invalid counts, overflow, predicates, and unsafe non-netted position deletes decline metadata COUNT. Tests cover an intentionally wrong positive snapshot summary and the principal proof/fallback states.
  • Scope and clarity: The functional change is concentrated in IcebergScanPlanProvider; the BE, metadata-statistics, and session-variable edits are explanatory. The exact-count and optimizer-estimate paths remain explicitly separated.
  • Concurrency: Count planning is synchronous and introduces no new shared mutable state or locks. The asynchronous streaming source retains its existing pinned-handle and backpressure ownership. The pre-pin batch estimate can change only the eager/streaming choice, not the snapshot used for rows.
  • Lifecycle: Both cache-backed count consumers place iterable creation, lazy iteration, close, failure recording, and fresh SDK retry inside the retry boundary. The per-file retry owns a fresh accumulator. No new leak, partial-reuse, or close-order issue survived review.
  • Configuration: No configuration key or default changes. ignore_iceberg_dangling_delete remains dynamically propagated through connector session properties, defaults to false, and its description now matches the deliberately approximate position-delete compatibility behavior.
  • Compatibility: No storage format, symbol, or thrift shape is added. The existing table_level_row_count carrier retains -1 as the decline sentinel and >= 0 (including zero) as a pushed count; V1 and V2 consumers preserve their established rolling-upgrade fences.
  • Parallel paths: Direct COUNT(*)/COUNT(1), filtered scans, equality/position deletes, format v3, cache-enabled/disabled planning, empty snapshots, current/ref/time-travel pins, optimizer statistics, and BE V1/V2 readers were traced. The two redundant-delete-read instances are the remaining mismatches and are called out inline.
  • Conditional checks: The filter, delete-state, overflow, negative-count, and empty-table gates all have an exact-or-decline interpretation. The negative-net streaming case is real but is the same gate and consequence already covered by discussion r3783138606, so it was not duplicated.
  • Test coverage: The FE unit suite covers wrong summaries, absent manifest aggregates, filters, empty snapshots, equality and position deletes, and eager/late manifest-cache failures. The missing format-v3 flagged-estimator and single-open synchronous representative cases are specified in the inline findings.
  • Test results: I did not build or run tests because the review-runner contract prohibits builds. At submission time CheckStyle, Clang Formatter, license, dependency, secrets, and performance checks are green; FE UT, BE UT, macOS BE UT, and compile checks are still pending.
  • Observability: Existing cache failure statistics and warning logs cover failure diagnosis. The accepted issues are successful-path redundant I/O rather than silent failures; no additional metric is necessary for the fix.
  • Transactions and persistence: Not applicable. The PR changes read planning only; it adds no EditLog, replay, persisted state, or transaction transition.
  • Data writes: Not applicable. No data mutation, commit, atomicity, or crash-recovery behavior changes.
  • FE/BE variables: No new cross-boundary variable is introduced. The existing count field and COUNT argument/runtime-filter fences are populated and consumed on the reviewed paths.
  • Performance: Manifest aggregates keep the common proof O(manifests), and the old-metadata fallback is O(files) with constant accumulator memory. However, successful flagged counts reread delete manifests during representative planning, and v3 batch estimation adds another avoidable read; these are the two P2 findings.
  • Other issues: All six changed paths and their directly affected production/test paths were reviewed. Four existing inline threads and replies were treated as known context; no duplicate was resubmitted.

User focus

No additional focus was supplied, so the full PR was reviewed without further narrowing.

Completion

Two accepted inline findings are included. Because the second was identified in the third and final allowed round, this review is capped/incomplete rather than converged; a refreshed pass after fixes may still be warranted.

return -1;
}
if (deleteState != ManifestDeleteState.PRESENT || netPositionDeletes) {
OptionalLong positionDeleteRows = livePositionDeleteRowCount(table, snapshot);

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] Keep the v3 fence ahead of the delete-manifest proof

On a format-v3 snapshot with live position deletes and ignore_iceberg_dangling_delete=true, this call opens and walks every live delete-file entry, then the COUNT block selects synchronous planning. But the unconditional v3 fence below makes that batch result invariant, and synchronous planCountPushdown calls livePositionDeleteRowCount again. The base ordering fenced v3 before this proof. For large position-delete/deletion-vector manifests, the estimator therefore adds a full remote metadata scan that cannot affect its result. Please move the v3 fence ahead of the COUNT block and cover the flagged v3/live-delete estimator path.

if (!visibleRows.isPresent()) {
return Optional.empty();
}
return planManifestCountRange(table, scan, visibleRows.getAsLong(), formatVersion,

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] Avoid rebuilding the delete index just to choose a COUNT representative

The global proof above has already opened every live delete manifest and either rejected equality deletes or obtained the position-delete count. This branch then chooses its first FileScanTask through scan.planFiles() or the cache-backed path; both eagerly reread all delete manifests to build a delete index before yielding that task. The range carries the exact table-level count, so BE short-circuits without applying the representative task's delete bindings. Successful flagged counts therefore pay a second full delete-manifest scan even when batch mode is disabled. Please obtain the representative data file without constructing unused delete bindings (or reuse the proof's entries), and test that synchronous flagged count planning opens each delete manifest only once.

@github-actions

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: Review step was failure (possibly timeout or cancelled)
Workflow run: https://github.com/apache/doris/actions/runs/31802626720

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

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 100% (0/0) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100% (0/0) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 74.78% (32049/42857)
Line Coverage 59.30% (355874/600166)
Region Coverage 55.57% (296598/533775)
Branch Coverage 56.51% (133790/236747)

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

Review status: complete/converged after Round 2. All three final-round reviewers returned NO_NEW_VALUABLE_FINDINGS, and every ledger candidate has a main-verified final status.

Summary opinion

The core exactness change is sound on the reviewed paths: unfiltered COUNT(*)/COUNT(1) reads a pinned Iceberg snapshot's live manifest state rather than optional snapshot-summary values, and unknown, invalid, overflowing, filtered, or unsafe delete states decline the metadata result and retain a real scan. I found no new actionable issue distinct from the existing review context, so this review adds no inline comments.

Two current-head P2 performance concerns remain open in the estimator ordering thread and the representative/delete-index thread. I did not duplicate them. A flagged negative-net estimator fallback is also substantially the same estimator/planner disagreement already covered by discussion r3783138606, so it was duplicate-suppressed under the review contract.

Critical checkpoint conclusions

  • Goal and proof: The implementation accomplishes the stated exact-count goal for the reviewed row domains. Manifest ADDED/EXISTING totals or the live-file fallback prove the data-row total at the selected snapshot; equality deletes, unsafe position deletes, malformed values, overflow, and negative subtraction fall back. Unit coverage includes a deliberately wrong snapshot summary, selected snapshots, deletes, filters, empty/zero results, old manifests, FE-to-BE population, and cache failures.
  • Scope and clarity: The functional work is focused in IcebergScanPlanProvider; the BE, connector-metadata, and session-variable changes align comments/contracts, and the obsolete summary-count test is replaced by provider-level coverage. No unrelated source change was found.
  • Concurrency: Planning uses request-local state and introduces no new thread, lock, lock ordering, atomic, or shared mutable state. Existing asynchronous streaming ownership and backpressure remain unchanged.
  • Lifecycle: Manifest/task iterables are closed through try-with-resources. Cached eager/lazy/close failures are caught at the consumer boundary, record one cache failure, and retry with fresh SDK iterables and fresh accumulator state. No new resource leak, partial-state reuse, or static-initialization concern was found.
  • Configuration: No configuration key or default is added. ignore_iceberg_dangling_delete retains its name, boolean type, persisted session behavior, dynamic request-scoped lookup, and default false; only its description changes.
  • Compatibility: No function symbol, persisted/storage format, or Thrift shape changes. The established optional table_level_row_count carrier still uses -1 to decline and nonnegative values, including zero, to push a result, preserving both BE scanner paths and mixed-version behavior.
  • Parallel paths: Direct COUNT semantics, static/runtime filter gates, TABLESAMPLE behavior, system tables, empty snapshots, current/ref/time-travel pins, cache/SDK planning, format v1-v3 deletes, rewrite scope, and both BE reader generations were traced. No additional parallel-path correctness issue was found; the remaining redundant-delete work is already covered by the two open P2 threads.
  • Conditional checks: Each new gate has an exact-or-decline interpretation. Missing/negative/overflow metadata and unsafe delete inventories do not emit an unproven nonnegative count. Similar estimator/count gates were checked and duplicate-fenced where already reported.
  • Test coverage: The changed FE units cover the central positive, negative, fallback, pinning, carrier, and cache-retry cases; the existing Iceberg COUNT regression and BE count-reader contracts cover the end-to-end carrier behavior. Additional edge tests could strengthen the matrix, but no uncovered edge justified a distinct correctness finding.
  • Test results: I did not build or run tests because the authoritative review bundle prohibits builds and test execution. At submission time, FE UT, BE UT, compile, external/P0 regressions, style, license, dependency, secrets, and performance checks are green; check_coverage_fe (Coverage) is failing, and this code-review job is still pending.
  • Observability: Existing scan profiles, contextual metadata errors, cache-failure statistics, and warning paths are sufficient for the changed behavior. No new metric or log is required for correctness.
  • Transactions and persistence: Not applicable; this is read planning and adds no EditLog, replay, transaction transition, or persisted state.
  • Data writes: Not applicable; no data mutation, commit, atomicity, or crash-recovery behavior changes.
  • FE/BE variables: No new cross-boundary variable is introduced. The existing count carrier and sentinel are populated and consumed consistently by the reviewed FE and BE paths.
  • Performance: The no-delete exact proof is O(manifests), while old metadata falls back to an O(files), constant-accumulator scan. The two avoidable delete-manifest rescans remain the open P2 discussions linked above; no distinct third performance issue survived deduplication.
  • Other issues: Error propagation, memory ownership, nullability, data-version visibility, and cloud/shared-nothing applicability were checked. Transactional write, persistence, and security review were not applicable to this read-planning change.

User focus and completion

No additional user-provided focus was supplied, so the full six-file change and its directly affected paths were reviewed. The review is complete/converged, not capped: Round 2 ended with no new valuable findings, no accepted new inline comments, and no unresolved ledger candidate.

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