Skip to content

[enhancement](scan) Backport Parquet V2 direct predicate filtering - #66360

Open
Gabriel39 wants to merge 4 commits into
apache:branch-4.1from
Gabriel39:fix/parquet-v2-direct-predicate-filtering-4.1
Open

[enhancement](scan) Backport Parquet V2 direct predicate filtering#66360
Gabriel39 wants to merge 4 commits into
apache:branch-4.1from
Gabriel39:fix/parquet-v2-direct-predicate-filtering-4.1

Conversation

@Gabriel39

@Gabriel39 Gabriel39 commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Proposed changes

Backport four selected commits from #66261 to branch-4.1 in their original order.

  • keep identity selection-vector state implicit and compact selected rows in bulk
  • refresh late runtime-filter requests at safe row-group boundaries
  • initialize refreshed JNI predicates
  • preserve Hudi/Paimon child-reader predicate state
  • remove query-scoped dictionary-filter cache state

Test

  • ./run-be-ut.sh --run '--filter=FileScannerV2Test.*:*Parquet*:*TableReaderTest.*:Hudi*ReaderTest.*:Paimon*ReaderTest.*:SelectionVectorTest.*:DictionaryFilterCostTest.*'
    • 627 tests from 47 test suites passed
  • git diff origin/branch-4.1...HEAD --check

@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

@Gabriel39
Gabriel39 marked this pull request as ready for review August 2, 2026 10:09
@Gabriel39
Gabriel39 requested a review from yiguolei as a code owner August 2, 2026 10:09

@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 two PR-introduced issues in the late runtime-filter refresh path:

  1. [P1] A COUNT(*) carrier that is still represented by synthesized placeholder defaults can be promoted to a late predicate while the active Parquet Row Group continues returning defaults; Scanner immediately evaluates the new RF and can silently drop or retain the wrong rows.
  2. [P2] Activating the new request retains footer-planning and adaptive-prefetch state derived from the old predicate snapshot, losing cheap pruning and potentially warming wide lazy output before a selective RF is sampled.

Critical checkpoint summary:

  • Runtime-filter lifecycle and COUNT(*) semantics: blocked by the placeholder transition above.
  • Parquet Row Group pruning and adaptive lazy-read state: needs request versioning or equivalent invalidation at activation.
  • Direct OR/NULL behavior, fused SelectionVector compaction, dictionary-reader reuse, and MergeRange ordering: no additional PR-introduced defect after focused recheck.
  • Mapping/layout compatibility, condition-cache handling, JNI/Hudi/Paimon forwarding, and expression ownership: no additional issue found.
  • Coverage: the changed tests exercise request queuing/activation, but not mid-Row-Group COUNT(*) result correctness or request-versioned multi-Row-Group I/O.
  • User focus: no additional focus was supplied; the full 39-file diff was reviewed.
  • Validation: static review only as required; no builds or tests were run.

}
RETURN_IF_ERROR(customize_file_scan_request(refreshed_request.get()));
if (_file_scan_request == nullptr ||
!same_physical_scan_layout(*refreshed_request, *_file_scan_request)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P1] Keep real COUNT() carrier values available until the refreshed request activates. When an RF promotes the current placeholder slot to a predicate, this compatibility check still accepts the request because positions/projections match. The Parquet scheduler does not activate it until the next row-group boundary, while Scanner::_filter_output_block() starts evaluating the new RF immediately; the active request has no reader for this slot and materializes defaults. For example, a current group containing ids [1,10] with a late id > 5 can test [0,0] and discard the matching row. Please avoid placeholdering possible RF carriers while filters are pending (or otherwise make the transition/fallback expose real values), and add a mid-row-group COUNT() refresh result test.

}
// Column readers and predicate schedules retain request-derived state for one row group. Swap
// only after they are gone; the refreshed request may promote a lazy column to a predicate.
_active_request = std::move(_pending_request);

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] Invalidate all predicate-snapshot-derived optimization state when this request becomes active. The unopened Row Group plans were footer-pruned with the old request, but their deferred finalization is EXPENSIVE_ONLY, so a late RF whose min/max rejects a group never gets the cheap footer-statistics pass. The old _predicate_survival_ratio/position stats also survive, allowing pre-RF dense batches to trigger full lazy-output prefetch before the new selective RF is sampled. Please make remaining planning/adaptive state request-versioned (or rerun current-request footer pruning and reset/preserve stats only when predicates are proven equivalent), with a multi-group late-RF I/O regression.

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 84.35% (582/690) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 73.48% (30083/40941)
Line Coverage 57.34% (328626/573104)
Region Coverage 54.40% (274595/504815)
Branch Coverage 55.24% (122089/221028)

@Gabriel39
Gabriel39 force-pushed the fix/parquet-v2-direct-predicate-filtering-4.1 branch from db8ebab to 4b5c6c4 Compare August 2, 2026 14:58
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