Skip to content

[improvement](be) Implement native Parquet decoding for FileScannerV2#65674

Open
Gabriel39 wants to merge 14 commits into
apache:masterfrom
Gabriel39:codex/fix-file-scanner-v2-native-decode
Open

[improvement](be) Implement native Parquet decoding for FileScannerV2#65674
Gabriel39 wants to merge 14 commits into
apache:masterfrom
Gabriel39:codex/fix-file-scanner-v2-native-decode

Conversation

@Gabriel39

@Gabriel39 Gabriel39 commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary:

FileScannerV2 previously used Arrow RecordReader/arrays/builders for Parquet value materialization and reconstructed complex columns through intermediate decoded objects. That path duplicated decode/materialization work, retained fragmented per-batch scratch, amplified string and nested-column memory usage, and made adaptive batches and cache/profile behavior diverge from the legacy v1 reader.

This PR implements an independent native Parquet read path under format_v2:

  • Decodes Parquet page V1/V2 definition/repetition levels and value streams without Arrow value readers.
  • Supports PLAIN, RLE/bit-packed dictionary indices, RLE booleans, DELTA_BINARY_PACKED, DELTA_LENGTH_BYTE_ARRAY, DELTA_BYTE_ARRAY, and BYTE_STREAM_SPLIT.
  • Keeps Decoder responsible for raw physical streams while DataTypeSerDe owns physical/logical conversion and direct append into final Doris columns.
  • Materializes dictionaries once into typed Doris state, validates every dictionary ID, and supports dictionary-filter index paths without rebuilding string values for rejected rows.
  • Reconstructs ARRAY/MAP/STRUCT shape from levels while leaf values go directly into Doris child columns; levels-only scans do not materialize payload values.
  • Reuses persistent normal-size decode, null-map, binary, selection, and level scratch; releases exceptional nested-batch allocations above a 4 MiB per-buffer high-water mark after parent offsets/null maps are consumed.
  • Uses a page-fragment hybrid selection path for highly selective scans: enter DataTypeSerDe once, then let each concrete encoding bulk-gather or batch-decode/compact selected values while advancing and validating the complete physical stream.
  • Keeps NULL-interleaving on the cursor-preserving fallback path and exposes HybridSelectionBatches, HybridSelectionRanges, and HybridSelectionNullFallbackBatches for diagnosis.
  • Aligns selection, adaptive batch sizing, footer/page cache, MergeRange behavior, and profiling counters with v1.
  • Removes the obsolete ParquetLeafBatch, PhysicalToLogicalConverter, Arrow builder/value-reader, and Arrow RecordReader fallback contracts from the v2 value path.
  • Leaves FE and the legacy be/src/format v1 implementation unchanged.

Arrow is now limited to the existing metadata/index/probe adapter boundary; it is not used to materialize scan values.

Release note

FileScannerV2 Parquet scans now use native Doris page/encoding decoding and direct DataTypeSerDe materialization instead of Arrow value readers.

Check List (For Author)

  • Test: Unit Test
    • Validation through commit d257ca06abf: remote ASAN BE build passed; targeted BE UT passed 91/91; LLVM 16 format check passed.
    • Commit 099c111c12f adds hybrid sparse decoding and decoder UT coverage. Build/UT validation was not run at the user's request; CI is requested below.
  • Behavior changed: Yes. FileScannerV2 Parquet values and levels use the native Doris decoder. Sparse non-null selections are decoded once per page fragment. Unsupported physical/logical/encoding combinations return explicit errors instead of falling back to Arrow value materialization.
  • Does this need documentation: Yes. Updated docs/file-scanner-v2-parquet-scan-design.md and docs/file-scanner-v2-code-review-guide.md.

@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

@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 completed. I found one issue in the FileScannerV2 Parquet reader changes: persistent scratch now extends Arrow binary chunk lifetimes after materialization/discard.\n\nValidation: static review only. git diff --check c8b81647776bcd482b99665530f9fd5ba41f0d03...0826614aff1d8bf5e21b78f8c8c5a0acfcb465de passed. I did not run build or unit/regression tests in this review-only checkout.

Comment thread be/src/format_v2/parquet/reader/scalar_column_reader.cpp Outdated
@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17953	4121	4119	4119
q2	2099	343	212	212
q3	10238	1404	837	837
q4	4686	477	348	348
q5	7512	855	591	591
q6	194	172	142	142
q7	757	844	636	636
q8	10287	1537	1632	1537
q9	6281	4376	4368	4368
q10	6856	1735	1469	1469
q11	498	343	323	323
q12	711	559	419	419
q13	18166	3367	2790	2790
q14	271	272	240	240
q15	q16	791	777	722	722
q17	977	990	856	856
q18	7156	5742	5460	5460
q19	1173	1289	1095	1095
q20	756	657	530	530
q21	5622	2644	2491	2491
q22	421	351	297	297
Total cold run time: 103405 ms
Total hot run time: 29482 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4359	4296	4301	4296
q2	281	327	219	219
q3	4613	4930	4402	4402
q4	2050	2164	1375	1375
q5	4384	4229	4268	4229
q6	226	180	128	128
q7	1995	2021	1638	1638
q8	2487	2167	2126	2126
q9	7755	7748	7699	7699
q10	4685	4650	4231	4231
q11	555	410	502	410
q12	761	754	535	535
q13	3245	3589	3019	3019
q14	299	300	290	290
q15	q16	718	737	652	652
q17	1361	1344	1320	1320
q18	8105	7303	6916	6916
q19	1139	1091	1086	1086
q20	2220	2200	1944	1944
q21	5254	4559	4389	4389
q22	519	472	415	415
Total cold run time: 57011 ms
Total hot run time: 51319 ms

@hello-stephen

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

query5	4339	621	485	485
query6	503	215	197	197
query7	4948	606	343	343
query8	344	191	177	177
query9	8758	3983	3983	3983
query10	449	349	287	287
query11	5905	2344	2135	2135
query12	154	104	101	101
query13	1286	619	448	448
query14	6279	5214	4884	4884
query14_1	4234	4223	4228	4223
query15	211	205	181	181
query16	1002	464	426	426
query17	1103	695	555	555
query18	2423	464	336	336
query19	203	197	148	148
query20	114	108	105	105
query21	235	157	128	128
query22	13538	13533	13310	13310
query23	17339	16402	16056	16056
query23_1	16147	16182	16191	16182
query24	7494	1756	1264	1264
query24_1	1304	1286	1285	1285
query25	552	461	380	380
query26	1351	341	207	207
query27	2608	629	382	382
query28	4507	1994	1980	1980
query29	1075	641	502	502
query30	344	259	225	225
query31	1121	1102	981	981
query32	104	62	64	62
query33	533	322	246	246
query34	1169	1129	619	619
query35	769	777	681	681
query36	1178	1182	1008	1008
query37	161	112	93	93
query38	1888	1700	1655	1655
query39	877	875	869	869
query39_1	837	826	841	826
query40	251	173	140	140
query41	72	68	69	68
query42	100	92	93	92
query43	319	321	284	284
query44	1454	770	744	744
query45	190	180	170	170
query46	1121	1204	736	736
query47	2171	2114	2027	2027
query48	399	427	297	297
query49	568	418	309	309
query50	1147	406	325	325
query51	10474	10754	10782	10754
query52	89	81	72	72
query53	247	269	206	206
query54	299	241	218	218
query55	76	70	64	64
query56	310	275	269	269
query57	1337	1266	1196	1196
query58	281	250	234	234
query59	1587	1643	1440	1440
query60	292	281	266	266
query61	150	147	154	147
query62	537	497	423	423
query63	239	202	208	202
query64	2806	1031	861	861
query65	4769	4642	4679	4642
query66	1802	507	363	363
query67	28705	29272	28963	28963
query68	3417	1512	1002	1002
query69	425	307	261	261
query70	1061	960	904	904
query71	335	318	285	285
query72	3086	2691	2377	2377
query73	789	788	422	422
query74	5065	4931	4700	4700
query75	2526	2512	2145	2145
query76	2343	1184	751	751
query77	345	391	269	269
query78	11903	11844	11414	11414
query79	1371	1208	763	763
query80	865	524	441	441
query81	504	330	285	285
query82	592	159	119	119
query83	396	319	288	288
query84	284	153	123	123
query85	989	576	498	498
query86	416	288	268	268
query87	1851	1824	1754	1754
query88	3695	2750	2769	2750
query89	529	364	330	330
query90	1772	203	194	194
query91	200	188	160	160
query92	62	63	58	58
query93	1601	1532	969	969
query94	649	367	323	323
query95	786	493	442	442
query96	1008	800	376	376
query97	2602	2634	2482	2482
query98	211	205	203	203
query99	1103	1123	980	980
Total cold run time: 262445 ms
Total hot run time: 176989 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.10	0.05	0.04
query3	0.26	0.14	0.14
query4	1.61	0.14	0.14
query5	0.24	0.22	0.22
query6	1.25	1.05	1.06
query7	0.04	0.00	0.00
query8	0.06	0.04	0.04
query9	0.37	0.33	0.31
query10	0.56	0.54	0.54
query11	0.20	0.14	0.14
query12	0.18	0.15	0.14
query13	0.48	0.47	0.49
query14	1.02	1.01	1.00
query15	0.63	0.60	0.58
query16	0.32	0.31	0.33
query17	1.10	1.14	1.12
query18	0.22	0.21	0.22
query19	2.05	1.95	1.90
query20	0.01	0.01	0.01
query21	15.44	0.20	0.13
query22	4.93	0.05	0.06
query23	16.13	0.31	0.13
query24	2.92	0.42	0.34
query25	0.11	0.06	0.05
query26	0.73	0.21	0.15
query27	0.05	0.04	0.04
query28	3.54	0.93	0.53
query29	12.47	4.11	3.31
query30	0.29	0.16	0.18
query31	2.78	0.61	0.31
query32	3.22	0.58	0.49
query33	3.13	3.22	3.20
query34	15.76	4.19	3.52
query35	3.52	3.50	3.52
query36	0.56	0.45	0.43
query37	0.10	0.06	0.07
query38	0.06	0.04	0.04
query39	0.04	0.04	0.03
query40	0.17	0.16	0.15
query41	0.09	0.03	0.04
query42	0.04	0.03	0.03
query43	0.04	0.03	0.04
Total cold run time: 96.83 s
Total hot run time: 25.08 s

@Gabriel39
Gabriel39 marked this pull request as ready for review July 16, 2026 00:14
@Gabriel39
Gabriel39 requested a review from yiguolei as a code owner July 16, 2026 00:14
Gabriel39 added a commit to Gabriel39/incubator-doris that referenced this pull request Jul 16, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#65674

Problem Summary: FileScannerV2 retained Arrow binary and dictionary chunks in persistent Parquet reader scratch after synchronous Doris materialization. Large binary batches could therefore stay alive until a later read and overlap the next Arrow builder allocation. Release batch payload ownership on every success and error path while retaining vector capacity, clear borrowed StringRef scratch before its owners are released, and add unit coverage for ownership release and capacity reuse. Also remove the previous decoder changes under the legacy format directory so the v1 implementation remains unchanged; future native decoder work is constrained to format_v2.

This lifecycle fix addresses the review finding but does not claim to eliminate the separate complex-column temporary materialization overhead. That v2-only decoder/materializer redesign remains distinct from COUNT(nullable_col) pushdown.

### Release note

None

### Check List (For Author)

- Test: Unit Test
    - Remote ASAN BE build
    - 16 focused Parquet v2 BE unit tests
    - Remote clang-format check
    - Remote clang-tidy attempted; blocked by existing diagnostics and the remote toolchain missing stddef.h during analysis
- Behavior changed: No; internal buffer ownership is released earlier
- Does this need documentation: Yes; updated the FileScannerV2 Parquet design document and format_v2 review guide
@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.

Review summary

Changes requested for one P1 memory-lifecycle regression. The allocation-reuse work is otherwise coherent, and the earlier Arrow-chunk ownership issue is fixed at the current head, but persistent nested scratch still lacks a bounded high-water release policy. See the inline comment.

Checkpoint conclusions

  • Goal and proof: The PR reduces FileScannerV2/Parquet allocation and materialization overhead and hardens several reader boundaries. The changed tests cover logical reset, object/capacity reuse, Arrow-owner release, dictionary validation, column mapping, and split Row Group accounting, but they do not prove that oversized nested scratch is released; that missing property is the finding.
  • Scope: The scanner, mapper, reader, statistics, Iceberg, tests, and design/guidance changes are focused on the stated optimization/hardening work.
  • Concurrency: Row Group reader trees are uniquely owned and invoked serially by the scanner; no new shared globals, locks, atomics, lock ordering, or reentrant access was found.
  • Lifecycle: Arrow chunks and borrowed StringRefs now unwind safely on success/error paths, resolving the existing thread. However, Doris-owned nested value/null/conversion/level/index backing allocations remain until Row Group teardown; the inline P1 covers this distinct defect.
  • Configuration: No configuration items or dynamic-reload behavior are added.
  • Compatibility: No storage-format, wire-protocol, symbol, or rolling-upgrade contract changes were found. Required-slot mapping is populated from the scan tuple for finalized and late-filter expressions, so removing the invalid ordinal fallback is safe.
  • Parallel paths: Parquet, ORC, text, JSON/native layout consumers continue to use stable local_positions; Scanner retains residual evaluation after lazy materialization. Dictionary, selection/page-skip, nested values/levels-only, List/Map/Struct, and Iceberg delete paths were also traced.
  • Conditions and errors: New slot/dictionary/selection validation returns checked errors; malformed partial reader state is terminal rather than retried. No speculative defensive continuation was introduced.
  • Test coverage: Unit coverage is broad for the changed local behaviors, including negative dictionary/selection cases, but needs the oversized repeated-value retained-allocation regression test requested inline.
  • Test results: No generated expected-result file changed. This review was static-only because the review contract prohibits builds in this runner.
  • Observability: Existing Status context and profile counters are sufficient for these local changes; Row Group candidate totals are corrected per Split and no new critical metric/log path is required.
  • Transactions and persistence: Not applicable; no transaction, EditLog, replay, or persistent metadata behavior changes.
  • Data writes: Not applicable; scan-side decoding and equality-delete filtering do not alter write atomicity or crash recovery.
  • FE/BE variables: No new transmitted variable or protocol field is introduced.
  • Performance: Normal-size scratch reuse removes hot-path allocations, but child-count-unbounded nested buffers can accumulate outlier high-water capacity and cause a new memory-limit failure. Other reviewed CPU/I/O/allocation paths showed no substantiated regression.
  • Other issues / user focus: No additional review focus was supplied. After three normal plus risk-focused convergence rounds, no second valuable finding or unresolved suspicious point remains.

Validation state

The live head is 913123e6cfeaa5712fd9571006a92e87f177f5a7. The author reports a remote ASAN build and focused unit tests, but I did not independently run them. Current formatter, license, FE UT, and Cloud UT checks pass. COMPILE, BE UT, and performance fail during CI setup because this head conflicts with current master in be/test/format_v2/parquet/parquet_reader_control_test.cpp; those jobs did not reach compilation/tests, and the PR is currently marked conflicting.

Comment thread be/src/format_v2/parquet/reader/parquet_leaf_reader.h Outdated
### What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary: FileScannerV2 currently materializes Parquet values through Arrow and repeatedly allocates conversion and nested-column scratch. Introduce an Arrow-independent physical column schema and selection-aware flat decode contract in the existing Doris Parquet kernel, batch string materialization, retain scalar and complex-reader scratch across batches, and document the target shared-level-plan interface for native complex decoding. The legacy v1 production call path remains unchanged.

### Release note

None

### Check List (For Author)

- Test: Unit Test
    - Remote ASAN BE build
    - 120 targeted Parquet BE unit tests
- Behavior changed: No; this adds migration interfaces and internal allocation optimizations
- Does this need documentation: Yes; updated the FileScannerV2 Parquet design document and format_v2 review guide
### What problem does this PR solve?

Issue Number: None

Related PR: apache#65674

Problem Summary: FileScannerV2 retained Arrow binary and dictionary chunks in persistent Parquet reader scratch after synchronous Doris materialization. Large binary batches could therefore stay alive until a later read and overlap the next Arrow builder allocation. Release batch payload ownership on every success and error path while retaining vector capacity, clear borrowed StringRef scratch before its owners are released, and add unit coverage for ownership release and capacity reuse. Also remove the previous decoder changes under the legacy format directory so the v1 implementation remains unchanged; future native decoder work is constrained to format_v2.

This lifecycle fix addresses the review finding but does not claim to eliminate the separate complex-column temporary materialization overhead. That v2-only decoder/materializer redesign remains distinct from COUNT(nullable_col) pushdown.

### Release note

None

### Check List (For Author)

- Test: Unit Test
    - Remote ASAN BE build
    - 16 focused Parquet v2 BE unit tests
    - Remote clang-format check
    - Remote clang-tidy attempted; blocked by existing diagnostics and the remote toolchain missing stddef.h during analysis
- Behavior changed: No; internal buffer ownership is released earlier
- Does this need documentation: Yes; updated the FileScannerV2 Parquet design document and format_v2 review guide
### What problem does this PR solve?

Issue Number: None

Related PR: apache#65674

Problem Summary: FileScannerV2 materialized ordinary Parquet values through Arrow arrays and temporary nested batches, which added allocation, conversion, and peak-memory overhead compared with the v1 reader. Route ordinary predicate and output columns through a persistent native reader that decodes directly into Doris columns, preserves selection and page-index coordinates, shares v1-compatible footer/page caches and MergeRange I/O, and keeps Arrow only for metadata planning, dictionary probing, and the existing COUNT complex levels-only path. Add detailed native decode profiles, adaptive-batch fragmentation profiles, complex/string/decimal/fixed-binary coverage, and update the Parquet design and review guidance. No FE or COUNT pushdown behavior is changed, and no be/src/format decoder code is modified.

### Release note

Improve FileScannerV2 Parquet scan memory use and native decode performance for scalar and complex columns.

### Check List (For Author)

- Test: Unit Test
    - 192 format v2 Parquet BE unit tests on the designated remote host
- Behavior changed: Yes (ordinary FileScannerV2 Parquet values use native direct materialization; query results and pushdown semantics are unchanged)
- Does this need documentation: Yes (design and review guide updated in this change)
### What problem does this PR solve?

Issue Number: close #xxx

Related PR: apache#65674

Problem Summary: The Parquet v2 native scan path no longer uses the prototype Arrow value-reader hierarchy, but its decoded leaf batch, nested load/build/consume protocol, factories, and tests remained reachable from a shape-only aggregate path. Remove that intermediate layer and isolate the unchanged COUNT(nullable_col) level-reading compatibility path behind a narrow API. Ordinary scans now expose only the persistent native read/skip/select contract.

### Release note

None

### Check List (For Author)

- Test: Unit Test (remote validation pending)
- Behavior changed: No
- Does this need documentation: Yes (updated in this commit)
### What problem does this PR solve?

Issue Number: None

Related PR: apache#65674

Problem Summary: FileScannerV2 still paid for an Arrow-decoded value layer or decoder-owned logical conversion before constructing Doris columns. This duplicated buffers for strings and nested values, amplified adaptive-batch memory peaks, and made dictionary, page-cache, and decode profiles difficult to compare with the v1 reader. Introduce an independent Parquet page/encoding reader under format_v2 whose decoders only parse encoded streams and own cursors. DataTypeSerDe now interprets Parquet physical and logical annotations and materializes selected values directly into persistent Doris columns. The native reader supports the existing scalar, decimal, date/time, timestamp, UUID, dictionary, delta, byte-stream-split, Page V1/V2, nested level, selection, page-index, footer/page-cache, and MergeRange paths. COUNT complex columns use a levels-only reader with persistent scratch, and page/decode/cache profiles expose cumulative deltas without duplicate counting. Arrow remains only in metadata/index planning and test fixture generation. No FE code or v1 format decoder is modified.

### Release note

Improve FileScannerV2 Parquet scan memory use and native decode performance, especially for strings, decimals, nested columns, dictionary selection, and adaptive batch sizes.

### Check List (For Author)

- Test: Unit Test
    - 14 Parquet decoder and DataTypeSerDe tests on the designated remote host
    - 76 Parquet v2 reader, selection, page-index, complex-column, and scan tests on the designated remote host
    - 6 focused COUNT/profile tests on the designated remote host
- Behavior changed: Yes (FileScannerV2 Parquet data pages materialize through the native v2 decoder and DataTypeSerDe; query semantics are unchanged)
- Does this need documentation: Yes (updated the FileScannerV2 Parquet design and review guide)
@Gabriel39
Gabriel39 force-pushed the codex/fix-file-scanner-v2-native-decode branch from 913123e to 78678d9 Compare July 16, 2026 11:36
### What problem does this PR solve?

Issue Number: None

Related PR: apache#65674

Problem Summary: Split the Parquet v2 decoder factory by encoding family and replace raw allocations with std::make_unique. This keeps decoder construction behavior unchanged while satisfying function-size and ownership static-analysis rules.

### Release note

None

### Check List (For Author)

- Test: Unit Test
    - Remote ASAN BE build and 90 Parquet v2/SerDe unit tests
    - Remote clang-tidy on the changed decoder factory
- Behavior changed: No
- Does this need documentation: No
### What problem does this PR solve?

Issue Number: None

Related PR: apache#65674

Problem Summary: Persistent Parquet v2 leaf readers reused level, null, selection, conversion, and dictionary-index scratch across batches. A legal repeated column can expand one logical batch into an exceptional number of leaf values, so staggered outliers could retain large allocations in multiple leaves until Row Group teardown. Keep normal-size capacity reusable, recursively release individual scratch buffers above a 4 MiB high-water mark after the top-level complex reader consumes the level plan, and cover the retained-capacity drop with a unit test.

### Release note

None

### Check List (For Author)

- Test: Unit Test
    - Remote ASAN ./build.sh --be
    - Remote Parquet v2 and SerDe unit-test suite
- Behavior changed: No
- Does this need documentation: Yes. Updated the FileScannerV2 Parquet design and review guide.
@Gabriel39 Gabriel39 changed the title [improvement](be) Optimize FileScannerV2 Parquet decoding [improvement](be) Implement native Parquet decoding for FileScannerV2 Jul 16, 2026
@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.

Review summary

Changes requested for 15 new, non-duplicate issues in the native Parquet reader. They cluster in three boundaries: shared footer/page-cache identity and immutability; exact decoder/page/level validation; and ARRAY/MAP/STRUCT shape preservation. The earlier Arrow-chunk ownership issue is fixed, and the existing nested-scratch high-water P1 remains active without being duplicated here.

Checkpoint conclusions

  • Goal and proof: The PR substantially implements native decoding and removes the old intermediate value path, but the current tests do not prove safe behavior for valid Page V1 BIT_PACKED levels, cache-order/version changes, decoder reuse, or several malformed-page/nested-shape cases covered by the inline findings.
  • Scope: The production, test, and design changes are focused on the stated FileScannerV2 Parquet migration, though the migration is broad enough that cache, decoder, selection, COUNT, and complex-column boundaries all needed end-to-end tracing.
  • Concurrency: Concurrent scans can share a cached FileMetaData; post-publication assign_ids() mutates it without synchronization. No other new lock-order or thread-entry issue was substantiated.
  • Lifecycle: Footer metadata is both option-dependent and mutated after publication; native S3 page keys lose the split's stable version; the reused delta-length decoder keeps stale/uninitialized state on empty pages. The existing nested-scratch retention thread remains separate.
  • Configuration: No new configuration item is added, but existing VARBINARY/TIMESTAMPTZ mapping options affect parsed schema and are missing from the shared footer-cache identity.
  • Compatibility: No storage or wire format is changed, but valid Page V1 BIT_PACKED definition/repetition levels are not supported by the non-bulk cursor paths, so existing files can fail or execute undefined behavior.
  • Parallel paths: Page V1/V2, compressed/uncompressed and cache-hit reads, selected/filtered/skipped values, normal nested scans and COUNT, v1/v2 footer-cache producers, and MAP/STRUCT sibling paths were checked. The findings identify the parallel instances that need the same exact validation.
  • Conditions and errors: Several decoder return values/counts are discarded, signed external sizes reach unsafe arithmetic/buffers, a malformed BYTE_STREAM_SPLIT payload reaches DORIS_CHECK, and release-only DCHECKs stand in for required corruption statuses.
  • Test coverage: Happy-path coverage is broad, but negative tests are missing for truncated BOOLEAN/delta/level streams, page-size and V2-level layout corruption, empty reused delta-length pages, null/misaligned MAPs, short siblings, leading continuations, and cache-order/version behavior. A concurrent same-footer cache test and valid BIT_PACKED Page V1 tests are also needed.
  • Test results: No generated regression .out file changed. The author reports remote ASAN build/focused-unit/format validation in the PR history; I did not independently run builds or tests under this review contract.
  • Observability: No new metric is required for these local failures; checked corruption statuses with file/column/page context are preferable to silent success, undefined behavior, or process termination.
  • Transactions and persistence: Not applicable; this is scan-side parsing/decoding and cache state, with no EditLog, replay, or transaction change.
  • Data writes: Not applicable; no table-data write, publish, or crash-recovery path is modified.
  • FE/BE variables: No new FE-to-BE transmitted variable or protocol field is introduced.
  • Performance: The native/materialization design removes intended allocations and copies, but correctness and bounded lifecycle must hold first. The existing P1 already covers retained outlier scratch; no additional non-duplicate performance regression was found.
  • Other issues / user focus: No extra user focus was supplied. After three normal/risk convergence rounds, the 15 inline findings below are the complete current non-duplicate set.

Validation state

The reviewed live head is d257ca06abff17c3a43f6f287594dc8dcf52ef80. This was static review only: the supplied contract prohibits builds, and this checkout has no .worktree_initialized, thirdparty/installed, or thirdparty/installed/bin/protoc.

Comment thread be/src/format_v2/parquet/parquet_file_context.cpp Outdated
Comment thread be/src/format_v2/parquet/parquet_file_context.cpp Outdated
Comment thread be/src/format_v2/parquet/reader/native/page_reader.cpp Outdated
Comment thread be/src/format_v2/parquet/reader/native/level_decoder.h Outdated
Comment thread be/src/format_v2/parquet/reader/native/bool_rle_decoder.cpp Outdated
Comment thread be/src/format_v2/parquet/reader/native/column_reader.cpp
Comment thread be/src/format_v2/parquet/reader/native/column_reader.cpp
Comment thread be/src/format_v2/parquet/reader/native/column_reader.cpp Outdated
Comment thread be/src/format_v2/parquet/reader/native/column_reader.cpp Outdated
Comment thread be/src/format_v2/parquet/reader/native/delta_bit_pack_decoder.h Outdated
@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17679	4132	4104	4104
q2	2044	351	197	197
q3	10261	1477	868	868
q4	4683	479	360	360
q5	7493	916	571	571
q6	198	190	144	144
q7	811	897	614	614
q8	9376	1626	1573	1573
q9	5602	4396	4336	4336
q10	6779	1753	1497	1497
q11	515	365	343	343
q12	745	586	465	465
q13	18136	3454	2720	2720
q14	270	278	247	247
q15	q16	794	785	716	716
q17	1018	1115	1002	1002
q18	7141	5788	5564	5564
q19	1314	1373	1085	1085
q20	810	695	626	626
q21	5994	2630	2359	2359
q22	435	365	306	306
Total cold run time: 102098 ms
Total hot run time: 29697 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4474	4403	4449	4403
q2	316	347	231	231
q3	4628	4962	4411	4411
q4	2202	2229	1403	1403
q5	4530	4348	4405	4348
q6	240	184	134	134
q7	2295	2043	1764	1764
q8	2901	2377	2334	2334
q9	8228	7909	7958	7909
q10	4714	4694	4240	4240
q11	598	433	401	401
q12	775	780	563	563
q13	3343	3632	2878	2878
q14	298	297	269	269
q15	q16	728	738	655	655
q17	1434	1526	1360	1360
q18	8155	7406	7351	7351
q19	1146	1071	1090	1071
q20	2247	2228	1928	1928
q21	5393	4779	4555	4555
q22	542	503	419	419
Total cold run time: 59187 ms
Total hot run time: 52627 ms

### What problem does this PR solve?

Issue Number: None

Related PR: apache#65674

Problem Summary: Highly selective Parquet v2 scans entered DataTypeSerDe and the encoding decoder once per selection run. Fragmented selections therefore amplified virtual dispatch, consumer construction, and cursor-management overhead. Add a page-fragment hybrid selection plan that enters SerDe once and lets each native encoding batch gather or compact selected values while preserving and validating the full physical cursor. Add profile counters, decoder coverage, scratch retention bounds, and design/review documentation.

### Release note

None

### Check List (For Author)

- Test: No test run (per user request)
- Behavior changed: Yes (sparse Parquet v2 materialization is batched per page fragment)
- Does this need documentation: Yes (included in this PR)
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

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

Requested changes: six new, deduplicated correctness and compatibility issues remain in the native Parquet-reader replacement.

Checkpoint conclusions:

  • Goal, scope, and tests: the native page/encoding/SerDe/scheduler/COUNT/cache architecture is broadly implemented and extensively tested, but behavioral parity is incomplete at the six inline boundaries below. Per the review contract, this was a static review only; I did not build or run tests. Missing focused coverage maps directly to INDEX_PAGE, PARQUET-816, pre-Arrow-3 V2 compression, non-strict nullable overflow, malformed nonempty OffsetIndexes, and invalid signed chunk ranges.
  • Concurrency, lifecycle, configuration: reader/decoder/scheduler state remains scan-local; shared cache/profile facilities keep established synchronization and teardown. No new thread, lock-order, static-initialization, lifecycle, or dynamic-config issue survived deduplication.
  • Compatibility and parallel paths: flat/nested, indexed/sequential, scalar/COUNT, dictionary/plain, V1/V2, cold/warm cache, direct/fallback conversion, predicate/lazy-output, and selected-range paths were checked. Findings 1-4 regress prior valid-file or scan semantics; findings 5-6 regress corruption boundaries and can return wrong data or cross chunk boundaries.
  • Error, memory, data correctness, and nullable handling: other inspected Status and bounds paths fail loudly. The unvalidated OffsetIndex can silently replay rows, the wrapped chunk range widens IO ownership, and direct materialization loses non-strict failure-to-NULL semantics. Existing MAP/STRUCT/decoder comments were not duplicated.
  • Observability and performance: the new profile hierarchy and counters cover the critical pipeline. Existing comments already own the substantiated allocation, scratch, cache, and complexity issues; no distinct additional metric or performance finding remained.
  • Persistence, writes, and FE/BE: this is a read-only external-file path with no Doris transaction, EditLog, persisted-format, data-write, or new FE-BE protocol change. The relevant existing BE session state, strict mode, becomes write-only as noted inline.
  • User focus: no additional focus was supplied; the whole PR was reviewed.

All 130 changed paths and all 37 existing inline comments were re-swept. Two normal full-review agents and the risk-focused agent converged on this exact six-comment state with NO_NEW_VALUABLE_FINDINGS.

Comment thread be/src/format_v2/parquet/parquet_file_context.cpp Outdated
Comment thread be/src/format_v2/parquet/reader/native/column_chunk_reader.cpp
Comment thread be/src/format_v2/parquet/reader/native/column_chunk_reader.cpp Outdated
Comment thread be/src/format_v2/parquet/reader/native/column_reader.cpp
Comment thread be/src/format_v2/parquet/reader/native/column_reader.cpp Outdated
Comment thread be/src/format_v2/parquet/reader/native/column_reader.cpp Outdated
@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.

Found three blocking correctness gaps in the native Parquet path:

  • INT96 direct materialization uses unchecked Julian-day/nanos arithmetic and can append an invalid timestamp while returning success.
  • TIMESTAMPTZ direct conversion neither checks millisecond scaling nor the 0001-9999 target range, including the decoded/statistics path.
  • OffsetIndex validation does not bind location zero to the metadata's first data page, allowing a shifted but monotonic index to skip and relabel page values.

Checkpoint summary:

  • Goal/scope and compatibility: the migration is coherently scoped, and legacy-writer/page-cache fixes plus PLAIN/dictionary/selection/count/nested paths were reviewed and deduplicated against existing threads; the three issues above remain.
  • Concurrency/lifecycle/configuration: footer-cache publication, reader ownership/reset, cancellation/profile flushing, MergeRange/FileCache routing, and session options showed no additional issue.
  • Parallel paths and tests: flat/nested, cold/warm cache, dictionary/plain, selected/skip, COUNT, alternate formats, and integration tests were covered. The inline comments identify missing boundary/corruption tests.
  • Persistence/write/FE-BE boundaries: this is a read-only BE change; no transactional, persistence, or FE-variable issue applies.
  • Performance/observability: adaptive scheduling, retained scratch, counters, and profile ownership showed no additional blocker.

Validation was static only, as the review task explicitly prohibited builds and test execution. No additional user-provided review focus was supplied.

Comment thread be/src/core/data_type_serde/data_type_datetimev2_serde.cpp Outdated
Comment thread be/src/core/data_type_serde/data_type_timestamptz_serde.cpp Outdated
Comment thread be/src/format_v2/parquet/reader/native/column_chunk_reader.cpp Outdated
### What problem does this PR solve?

Issue Number: None

Related PR: apache#65674

Problem Summary: Parquet INT96 conversion could overflow signed arithmetic or accept an invalid nanos-of-day, TIMESTAMPTZ millisecond scaling could overflow or materialize values outside years 0001-9999, and a uniformly shifted OffsetIndex could still pass monotonic range validation. Use a shared checked timestamp conversion for direct, dictionary, and decoded/statistics paths, preserve strict rollback and non-strict NULL propagation, and anchor the first OffsetIndex location to the owning data_page_offset.

### Release note

None

### Check List (For Author)

- Test: Unit Test
    - DataTypeSerDeParquetTest.* and ParquetV2NativeDecoderTest.* (60 tests)
- Behavior changed: Yes (invalid Parquet timestamps are rejected or converted to NULL according to load strictness, and incoherent OffsetIndex metadata falls back to sequential traversal)
- Does this need documentation: Yes (updated the review guide and Parquet scan design in apache#65674)
@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 completed after three full-diff and exact-set convergence rounds. Requesting changes for five P1 issues: two direct-decimal correctness/compatibility regressions, missing level-domain validation, an unbounded nested-level allocation from page metadata, and unbounded retained lazy-skip bitmaps.

Checkpoint conclusions:

  • Goal, scope, and tests: The native V2 decode replacement and associated cache/profile work broadly implement the intended goal and add extensive BE coverage, but the negative schema-evolution, malformed-level/page, and long-prefix resource cases in the inline comments are missing. The patch is not yet safe to merge.
  • Concurrency and lifecycle: Persistent row-group readers, cache handles, MergeRange ownership, profile snapshot publication, and normal/error close paths were traced; no new lock, deadlock, use-after-free, or double-publication issue remains.
  • Compatibility, parallel paths, and conditions: Plain and dictionary encodings, strict and nullable non-strict conversion, V1/V2 pages, flat/nested readers, scalar/COUNT paths, and cache hit/miss behavior were checked. No protocol, config, or storage-format change was introduced; the blocking compatibility gaps are the decimal direct paths called out inline.
  • Tests, results, and observability: Added unit tests and profile counters are generally coherent, but the five negative/resource cases are absent. No generated-result issue was found. No build or tests were run because the review-runner contract requires static review only.
  • Persistence, writes, and FE/BE variables: Not applicable; this is a BE read-path change.
  • Performance and memory: The two allocation findings are blocking because valid selective scans or tiny malformed pages can cause memory use far beyond the requested batch.
  • User focus: No additional focus points were supplied.

Comment thread be/src/format_v2/parquet/reader/native_column_reader.cpp
Comment thread be/src/core/data_type_serde/data_type_decimal_serde.cpp Outdated
Comment thread be/src/format_v2/parquet/reader/native/level_decoder.cpp Outdated
Comment thread be/src/core/data_type_serde/data_type_decimal_serde.cpp Outdated
Comment thread be/src/format_v2/parquet/reader/native/column_chunk_reader.cpp Outdated
@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.

Request changes: I found three P1 correctness/nontermination issues and four P2 compatibility/profile-accounting issues in the native Parquet and FileScannerV2 integration. Existing review threads and all raw inline comments were deduplicated; the previously reported shifted MAP repetition issue is intentionally not repeated.

Critical checkpoint conclusions:

  • Goal and tests: the native decoder/direct-materialization goal is implemented broadly, but the accepted page-cardinality, nested-progress, and projection failures show the current head does not yet preserve correctness for all supported inputs. Focused negative tests are missing for each accepted case.
  • Scope and focus: this is a large but coherent BE reader replacement plus cross-format profile refactor, not a local change. No additional user focus was supplied, so the complete 125-file change set was reviewed.
  • Concurrency: cache metadata/page-range publication and close/profile publication use mutex or at-most-once/delta protection; no new distinct race or lock-order issue survived review. No new thread entry is introduced.
  • Lifecycle and static initialization: three P2 timer defects are reported below. No cross-TU static-initialization dependency or ownership cycle was found.
  • Configuration: no configuration item is added, so dynamic-update behavior is not applicable.
  • Compatibility: no FE/BE protocol or persisted-format change is introduced. One P2 comment covers rejection of a format-valid large V1 BIT_PACKED page; rolling-upgrade handling is otherwise not implicated.
  • Parallel paths and conditions: V1/V2, indexed/sequential, selected/skip, plain/dictionary, nested/scalar, JNI/native, Iceberg delete, abort, EOF, and parallel format/profile paths were traced. Existing related issues were suppressed as duplicates.
  • Error, memory, null, and data correctness: malformed cardinalities must fail instead of shifting rows or spinning; full nested projection must not default or fatal. Nullable/conversion, allocation, encoding, timestamp, and cache concerns already present in review context were not duplicated.
  • Test coverage and results: the changed tests are extensive but do not cover the seven reported failures. This review was static-only by contract; no local build or tests were run. The PR body reports remote ASAN/focused 91/91 validation through d257ca0 and explicitly says the later hybrid commit was not built/unit-tested, so that earlier result does not validate the full current head.
  • Observability: the hierarchy is useful, but the reported late, omitted, and overlapping timers make key values unreliable until fixed. Other profile publication paths use snapshot/delta or at-most-once guards.
  • Transactions, persistence, and data writes: not involved; no EditLog, transactional mutation, or crash-atomicity path changes.
  • FE/BE variables: none added or transmitted.
  • Performance: native/direct decoding and bounded scratch target the intended CPU/memory improvements; no additional substantiated performance defect survived beyond existing threads.
  • Other issues: all suspicious points have a submitted, duplicate, or evidence-backed dismissed conclusion, and three reviewers converged on this exact seven-comment set.

Validation: static review only; no local build or tests were run.

Comment thread be/src/format_v2/parquet/reader/native/column_chunk_reader.cpp
Comment thread be/src/format_v2/parquet/reader/native/level_decoder.cpp
Comment thread be/src/format_v2/parquet/reader/native/column_chunk_reader.cpp
Comment thread be/src/format_v2/parquet/reader/native_column_reader.cpp
Comment thread be/src/format_v2/table_reader.cpp
Comment thread be/src/format_v2/table_reader.cpp
Comment thread be/src/format_v2/table/iceberg_position_delete_sys_table_reader.cpp
@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 74.15% (5841/7877) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 57.54% (24181/42023)
Line Coverage 41.41% (238954/577095)
Region Coverage 37.24% (189108/507842)
Branch Coverage 38.30% (84753/221296)

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17656	4120	4113	4113
q2	2054	333	211	211
q3	10291	1443	865	865
q4	4687	477	344	344
q5	7529	890	582	582
q6	182	178	145	145
q7	786	861	648	648
q8	9358	1529	1629	1529
q9	5586	4346	4374	4346
q10	6769	1758	1497	1497
q11	524	354	333	333
q12	738	582	462	462
q13	18139	3473	2805	2805
q14	267	270	245	245
q15	q16	790	788	718	718
q17	1064	1079	948	948
q18	7065	5945	5602	5602
q19	1190	1311	1084	1084
q20	791	691	606	606
q21	5736	2710	2459	2459
q22	430	362	298	298
Total cold run time: 101632 ms
Total hot run time: 29840 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4384	4313	4322	4313
q2	287	319	218	218
q3	4616	4972	4381	4381
q4	2069	2139	1356	1356
q5	4438	4286	4302	4286
q6	236	179	133	133
q7	1744	2143	1734	1734
q8	2597	2183	2206	2183
q9	8104	8131	7824	7824
q10	4702	4674	4309	4309
q11	582	439	389	389
q12	748	772	537	537
q13	3323	3607	2905	2905
q14	290	301	283	283
q15	q16	710	720	633	633
q17	1398	1348	1451	1348
q18	7909	7439	7420	7420
q19	1190	1118	1151	1118
q20	2223	2211	1925	1925
q21	5242	4522	4414	4414
q22	527	470	420	420
Total cold run time: 57319 ms
Total hot run time: 52129 ms

@hello-stephen

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

query5	4341	630	503	503
query6	467	234	223	223
query7	4956	631	336	336
query8	343	200	170	170
query9	8805	4129	4149	4129
query10	496	355	302	302
query11	5844	2323	2178	2178
query12	166	102	107	102
query13	1272	603	416	416
query14	6353	5265	4928	4928
query14_1	4616	4234	4294	4234
query15	210	208	185	185
query16	1036	484	494	484
query17	1125	705	583	583
query18	2706	482	353	353
query19	215	197	160	160
query20	114	112	106	106
query21	238	173	140	140
query22	13521	13452	13360	13360
query23	17506	16590	16102	16102
query23_1	16272	16303	16306	16303
query24	7539	1806	1300	1300
query24_1	1300	1323	1307	1307
query25	586	476	396	396
query26	1343	383	228	228
query27	2433	622	388	388
query28	4360	2011	2010	2010
query29	1082	632	506	506
query30	347	270	228	228
query31	1121	1101	989	989
query32	112	62	63	62
query33	521	327	254	254
query34	1188	1130	655	655
query35	770	783	678	678
query36	1203	1205	1065	1065
query37	161	116	138	116
query38	1861	1693	1648	1648
query39	874	894	851	851
query39_1	841	830	850	830
query40	241	166	142	142
query41	67	63	66	63
query42	94	100	91	91
query43	331	343	290	290
query44	1441	769	764	764
query45	200	185	181	181
query46	1048	1157	722	722
query47	2085	2115	1969	1969
query48	395	430	301	301
query49	573	422	319	319
query50	1065	447	348	348
query51	10607	10667	10620	10620
query52	94	86	73	73
query53	268	285	204	204
query54	290	231	248	231
query55	75	76	66	66
query56	302	286	291	286
query57	1314	1263	1181	1181
query58	302	270	264	264
query59	1630	1673	1416	1416
query60	333	271	252	252
query61	148	143	150	143
query62	540	500	428	428
query63	232	202	199	199
query64	2787	1043	889	889
query65	4724	4614	4672	4614
query66	1775	509	379	379
query67	29301	29252	29023	29023
query68	3114	1427	1010	1010
query69	411	304	274	274
query70	1077	970	1009	970
query71	391	336	319	319
query72	3070	2688	2380	2380
query73	886	785	408	408
query74	5068	4915	4692	4692
query75	2541	2520	2136	2136
query76	2317	1214	804	804
query77	355	367	284	284
query78	11919	11839	11284	11284
query79	1478	1128	761	761
query80	1310	566	468	468
query81	527	342	302	302
query82	616	157	121	121
query83	368	324	303	303
query84	288	160	135	135
query85	974	592	523	523
query86	433	293	282	282
query87	1845	1821	1762	1762
query88	3770	2806	2789	2789
query89	442	377	330	330
query90	2010	206	199	199
query91	204	195	161	161
query92	60	62	53	53
query93	1728	1527	1047	1047
query94	714	348	343	343
query95	781	602	483	483
query96	1026	858	371	371
query97	2656	2613	2484	2484
query98	216	207	205	205
query99	1082	1127	965	965
Total cold run time: 264475 ms
Total hot run time: 178306 ms

@hello-stephen

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

query1	0.01	0.00	0.00
query2	0.10	0.04	0.05
query3	0.26	0.16	0.13
query4	1.61	0.14	0.14
query5	0.25	0.24	0.23
query6	1.24	1.07	1.07
query7	0.04	0.01	0.01
query8	0.05	0.03	0.03
query9	0.40	0.32	0.31
query10	0.57	0.56	0.59
query11	0.19	0.14	0.13
query12	0.18	0.13	0.14
query13	0.47	0.49	0.50
query14	1.02	0.99	1.00
query15	0.62	0.63	0.59
query16	0.30	0.32	0.32
query17	1.12	1.15	1.10
query18	0.23	0.21	0.22
query19	2.13	1.99	1.97
query20	0.02	0.01	0.01
query21	15.47	0.20	0.13
query22	4.85	0.06	0.05
query23	16.13	0.31	0.12
query24	2.96	0.42	0.34
query25	0.12	0.05	0.04
query26	0.72	0.20	0.14
query27	0.04	0.04	0.04
query28	3.55	0.98	0.54
query29	12.51	4.15	3.32
query30	0.26	0.15	0.16
query31	2.77	0.57	0.31
query32	3.22	0.59	0.49
query33	3.13	3.18	3.20
query34	15.57	4.14	3.52
query35	3.53	3.55	3.58
query36	0.54	0.43	0.42
query37	0.09	0.07	0.06
query38	0.06	0.03	0.03
query39	0.03	0.04	0.03
query40	0.17	0.16	0.16
query41	0.09	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.7 s
Total hot run time: 25.17 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 81.74% (6422/7857) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.56% (30978/40998)
Line Coverage 60.13% (344858/573565)
Region Coverage 57.07% (290929/509735)
Branch Coverage 58.41% (129350/221438)

@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: Selected model is at capacity. Please try a different model.
Workflow run: https://github.com/apache/doris/actions/runs/29595389233

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

------ Round 1 ----------------------------------
============================================
q1	17700	4054	4091	4054
q2	2015	320	198	198
q3	10303	1423	832	832
q4	4689	466	339	339
q5	7566	849	551	551
q6	197	178	136	136
q7	735	810	611	611
q8	9960	1566	1699	1566
q9	5956	4334	4339	4334
q10	6773	1719	1449	1449
q11	514	351	329	329
q12	748	580	446	446
q13	18171	3307	2777	2777
q14	265	262	247	247
q15	q16	787	775	709	709
q17	1037	981	952	952
q18	6761	5625	5486	5486
q19	1759	1321	1101	1101
q20	813	676	580	580
q21	5799	2646	2488	2488
q22	435	351	295	295
Total cold run time: 102983 ms
Total hot run time: 29480 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4457	4355	4355	4355
q2	287	307	215	215
q3	4554	4995	4412	4412
q4	2027	2124	1365	1365
q5	4442	4275	4251	4251
q6	234	175	125	125
q7	1717	2144	1708	1708
q8	2500	2161	2258	2161
q9	7816	7802	7723	7723
q10	4687	4684	4211	4211
q11	599	433	366	366
q12	930	753	531	531
q13	3224	3532	3011	3011
q14	302	300	297	297
q15	q16	733	731	630	630
q17	1340	1297	1345	1297
q18	8086	7401	7253	7253
q19	1160	1094	1123	1094
q20	2225	2216	1932	1932
q21	5153	4528	4357	4357
q22	503	457	426	426
Total cold run time: 56976 ms
Total hot run time: 51720 ms

@hello-stephen

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

query5	4316	641	469	469
query6	473	231	203	203
query7	4851	584	336	336
query8	367	194	172	172
query9	8774	4095	4057	4057
query10	469	382	294	294
query11	5955	2330	2104	2104
query12	156	103	101	101
query13	1253	628	434	434
query14	6266	5179	4850	4850
query14_1	4239	4225	4219	4219
query15	217	216	185	185
query16	1011	479	439	439
query17	1077	717	582	582
query18	2430	474	360	360
query19	211	194	153	153
query20	113	108	104	104
query21	228	157	137	137
query22	13557	13548	13296	13296
query23	17294	16380	16085	16085
query23_1	16192	16239	16230	16230
query24	7581	1787	1275	1275
query24_1	1305	1301	1290	1290
query25	559	471	390	390
query26	1334	340	218	218
query27	2660	591	372	372
query28	4435	2020	2001	2001
query29	1082	618	496	496
query30	351	269	230	230
query31	1133	1091	993	993
query32	109	64	64	64
query33	547	329	263	263
query34	1184	1120	645	645
query35	766	795	691	691
query36	1196	1158	1036	1036
query37	158	111	95	95
query38	1859	1708	1669	1669
query39	891	882	842	842
query39_1	832	854	838	838
query40	254	171	177	171
query41	69	62	67	62
query42	90	90	89	89
query43	325	334	279	279
query44	1439	775	761	761
query45	193	183	170	170
query46	1076	1218	698	698
query47	2126	2065	2058	2058
query48	400	376	299	299
query49	589	423	304	304
query50	1132	425	323	323
query51	11184	10778	11040	10778
query52	83	85	73	73
query53	263	285	205	205
query54	274	227	224	224
query55	77	70	64	64
query56	309	294	275	275
query57	1317	1275	1154	1154
query58	303	240	261	240
query59	1633	1594	1430	1430
query60	301	269	255	255
query61	163	149	152	149
query62	542	500	428	428
query63	240	202	206	202
query64	2799	1049	897	897
query65	4750	4666	4608	4608
query66	1821	505	380	380
query67	29383	29289	29151	29151
query68	3173	1545	972	972
query69	419	302	271	271
query70	1025	990	938	938
query71	374	342	319	319
query72	3058	2736	2402	2402
query73	866	801	431	431
query74	5050	4960	4746	4746
query75	2521	2510	2130	2130
query76	2352	1181	784	784
query77	352	378	282	282
query78	11766	11835	11413	11413
query79	2519	1115	760	760
query80	1723	566	456	456
query81	516	329	284	284
query82	597	156	120	120
query83	379	319	297	297
query84	305	160	135	135
query85	982	605	533	533
query86	416	292	288	288
query87	1832	1827	1753	1753
query88	3700	2808	2782	2782
query89	438	371	339	339
query90	1892	196	189	189
query91	198	189	162	162
query92	62	63	59	59
query93	1775	1537	943	943
query94	725	361	310	310
query95	783	525	492	492
query96	1062	789	371	371
query97	2603	2632	2466	2466
query98	215	205	201	201
query99	1090	1116	963	963
Total cold run time: 265547 ms
Total hot run time: 177428 ms

@hello-stephen

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

query1	0.01	0.01	0.00
query2	0.10	0.05	0.05
query3	0.25	0.14	0.13
query4	1.61	0.13	0.13
query5	0.24	0.24	0.21
query6	1.22	1.10	1.06
query7	0.04	0.01	0.01
query8	0.06	0.04	0.04
query9	0.37	0.31	0.31
query10	0.56	0.58	0.55
query11	0.19	0.13	0.13
query12	0.18	0.14	0.14
query13	0.47	0.49	0.49
query14	1.02	1.02	1.01
query15	0.62	0.59	0.60
query16	0.34	0.32	0.31
query17	1.07	1.12	1.07
query18	0.23	0.22	0.21
query19	2.04	1.94	2.00
query20	0.01	0.01	0.01
query21	15.40	0.23	0.14
query22	4.82	0.06	0.06
query23	16.11	0.31	0.12
query24	2.98	0.44	0.32
query25	0.11	0.05	0.05
query26	0.72	0.20	0.14
query27	0.05	0.04	0.03
query28	3.54	0.94	0.53
query29	12.47	4.14	3.27
query30	0.28	0.15	0.16
query31	2.77	0.59	0.32
query32	3.22	0.58	0.48
query33	3.23	3.24	3.31
query34	15.71	4.24	3.55
query35	3.52	3.54	3.55
query36	0.55	0.45	0.42
query37	0.08	0.07	0.06
query38	0.06	0.04	0.04
query39	0.03	0.03	0.04
query40	0.18	0.16	0.16
query41	0.08	0.03	0.03
query42	0.03	0.02	0.02
query43	0.05	0.03	0.04
Total cold run time: 96.62 s
Total hot run time: 25.12 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 74.31% (5978/8045) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 57.58% (24196/42025)
Line Coverage 41.46% (239339/577208)
Region Coverage 37.28% (189380/508053)
Branch Coverage 38.33% (84841/221340)

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 81.57% (6546/8025) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 74.93% (30722/41000)
Line Coverage 59.27% (340032/573678)
Region Coverage 55.86% (284880/509946)
Branch Coverage 57.11% (126488/221482)

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

Request changes. I found three new issues in the native Parquet path: two P1 optional-index boundary failures (an unbounded serialized-index allocation and false-negative IS NULL pruning from contradictory null metadata) plus one P2 cache-disabled V2 level-copy regression.

Checkpoint summary:

  • Goal, scope, and tests: the Arrow-to-native materialization goal is coherent and the PR adds broad SerDe, decoder, nested-reader, scheduling, cache, compatibility, and profile coverage. The three inline cases still need focused fallback/correctness/performance tests.
  • Correctness and compatibility: I checked flat/nested, plain/dictionary, indexed/sequential, selected/skipped, page-crossing, strict/non-strict, old-writer, and compressed/uncompressed V2 paths. Existing cardinality, decoder, decimal, timestamp, and projection findings were deduplicated rather than repeated.
  • Concurrency, lifecycle, and observability: shared metadata/cache publication and cleanup/profile paths were reviewed. No additional distinct concurrency issue survived; the current lifecycle/profile threads remain applicable.
  • Configuration and performance: cache enable/disable and mapping/compatibility options were traced. The cache-disabled V2 copy and optional-index memory exposure are the new surviving performance/resource issues.
  • Transactions, writes, and FE/BE variable propagation: not applicable to this read-path change.
  • User focus: no additional focus was provided.

This was a static review as required by the runner contract; I did not build or run tests. All 134 authoritative changed paths were swept, and the independent full/risk reviews converged on this exact comment set with no further valuable findings.


const int64_t span_offset = (*ranges)[range_begin].offset;
const int64_t span_length = span_end - span_offset;
std::vector<uint8_t> serialized(static_cast<size_t>(span_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.

[P1] Bound optional index reads before allocating them

Each individual footer range is accepted up to the integer limit when it merely fits inside the file, and adjacent ranges across projected leaves are merged here without an aggregate budget. A large object can therefore advertise one roughly-2-GiB index (or several adjacent ones) and make this optional pruning path allocate a multi-gigabyte std::vector before Thrift parsing can reject it; the OffsetIndex-only loader has the same whole-range allocation at line 793. Please cap individual and coalesced serialized-index bytes (using tracked storage where applicable) and conservatively skip the optional index above that budget, with large-length/adjacent-range fallback tests.

return false;
}
page_statistics->has_null_count = true;
page_statistics->has_null = column_index.null_counts[page_idx] > 0;

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] Reject contradictory ColumnIndex null metadata before pruning

The native loader checks the null_pages vector length but not these counts or their consistency. For a positive-row page with null_pages[i] = true and null_counts[i] = 0 (or a negative count), this produces a zone map with both has_null and has_not_null false. IS NULL then evaluates to kNoMatch, so an all-null page can be removed without evaluating its data. Please invalidate/fall back from the optional ColumnIndex on negative or contradictory null metadata, and add native PageIndex tests for IS NULL/IS NOT NULL with those cases.

if (_block_compress_codec != nullptr) {
Slice compressed_data;
RETURN_IF_ERROR(_page_reader->get_page_data(compressed_data));
std::vector<uint8_t> level_bytes;

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 copying V2 levels when the page cannot be cached

This allocates and copies every repetition/definition byte before checking whether the session cache is enabled, storage caching is globally disabled, or a cache instance exists. The live decoders use _v2_rep_levels/_v2_def_levels slices into the page buffer; level_bytes is consumed only by _insert_page_into_cache. Thus cache-disabled nested V2 scans still pay one allocation, memcpy, and free per page. Please build this buffer only inside cache admission (or reuse bounded scratch only for an actual insertion), with a cache-disabled coverage hook/benchmark.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants