feat(scanner): push dynamic filters into FilteredReadExec#7836
Draft
wjones127 wants to merge 1 commit into
Draft
feat(scanner): push dynamic filters into FilteredReadExec#7836wjones127 wants to merge 1 commit into
wjones127 wants to merge 1 commit into
Conversation
Implement DataFusion 54's physical filter-pushdown protocol on FilteredReadExec so dynamic filters produced by upstream operators (a TopK SortExec, a hash join) are threaded into the scan and applied per batch. The scan then drops rows before they flow into the downstream sort / take, and because a DynamicFilterPhysicalExpr re-reads its current predicate on every batch, a TopK threshold that tightens during execution is honored. - FilteredReadExec: handle_child_pushdown_result absorbs Post-phase filters that are evaluable against its output schema; they are applied as a per-batch post-projection filter. - TakeExec: forward filters that reference only input columns to its child so they can reach the scan below it. - scanner: install FilterPushdown(Post) in the physical optimizer set. Only the Post phase is installed; static WHERE predicates stay on Lance's logical filter path. Refs lance-format#7562 Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: QUIET Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Makes
FilteredReadExeca first-class DataFusion physical filter-pushdown sink (likeDataSourceExec), so dynamic filters produced by upstream operators are threaded into the scan and evaluated there instead of only above it. Draft for #7562.What changed
FilteredReadExecimplementshandle_child_pushdown_result(Post phase). It absorbs any offered filter whose columns are all produced by the scan, stores it, and applies it as a per-batch filter on the fully-projected output.gather_filters_for_pushdownis left at its default, mirroringDataSourceExec.TakeExecforwards filters that reference only its input's columns down to its child (mirrorsCoalesceBatchesExec), so a filter can reach the scan beneath a take. Filters on take-added columns stay above it.FilterPushdown::new_post_optimization()inget_physical_optimizer(). Post phase only — staticWHEREpredicates are already baked intofull_filterby Lance's logical filter plan, so running the Pre phase here would double-apply them.A
DynamicFilterPhysicalExprre-reads its current predicate on everyevaluate, so a TopK threshold that tightens as the sort's heap fills is honored per batch without re-planning.Verified benefit: TopK (
ORDER BY … LIMIT)SELECT id, value FROM t ORDER BY value LIMIT 10now plans as:The scan drops rows the top-k provably can't contain before they reach the sort. With a wide, late-materialized column the win compounds — the scan reads only the narrow sort key, and the downstream
Takefetches the wide column for the surviving rows only:Scope / honest limitations
This is deliberately the smallest useful slice — the reusable protocol spine plus CPU pruning (rows dropped at the scan). Two larger wins are follow-ups:
ZoneMapIndex/btree probe of the filter'sIsIn/Range(both already answerSargableQuery) would give Parquet-style range skipping. Depends on Always update zone map index during write time #4522 (ubiquitous zone maps) and Change SargableQuery::IsIn to hold an Arrow array instead of Vec<ScalarValue> #7192 (largeIsIn).LanceReadis the hash-join build side (CollectLeft,Inner), so DataFusion pushes the join's dynamic filter to the probe (the source), not the target scan. Filtering the target by source keys needs a join-side change, tracked separately.Tests
test_topk_dynamic_filter_pushdown— multi-fragment TopK: the dynamic filter reachesLanceReadand results are exactly the true top-k.test_handle_child_pushdown_result_absorbs_dynamic_filter— unit test: Post-phase absorbs and rewrites (Pre-phase declines); a filter tightened after pushdown takes effect at execute time.test_take_filter_pushdown_pass_through—TakeExecroutes an input-column filter down and keeps a take-added-column filter above.cargo fmtandcargo clippy -p lance --tests -- -D warningspass.