feat: Adds IntervalJoinExec for point-in-interval range joins#21859
feat: Adds IntervalJoinExec for point-in-interval range joins#21859SubhamSinghal wants to merge 3 commits into
Conversation
This is a cool idea. I got a question: for this predicate The existing Piecewise Merge join has already implemented the above idea, though the residual filter has't been implemented yet. |
|
If needed, we can also sort by |
This idea has been already implemented in , though it's not working right now, it will work if the predicate only includese.time >= w.start, but it requires some follow-up work for remaining filters handling (like e.time < w.end)
This is a good idea to explore in the future! I think For coordination, I’m hoping to refactor PWMJ to build on top of the |
|
@2010YOUY01 Thanks for the feedback. I will refactor code once JoinAccelerator API is ready. |
|
Thank you for your contribution. Unfortunately, this pull request is stale because it has been open 60 days with no activity. Please remove the stale label or comment or this will be closed in 7 days. |
Which issue does this PR close?
Rationale for this change
Point-in-interval range joins (
e.time >= w.start AND e.time < w.end) currently fall through to NestedLoopJoin whichis O(N×M). This adds a specialized
IntervalJoinExecoperator that uses a sort-merge approach — O(N log N + M log M +scan) — with sequential memory access and no intermediate JoinFilter batch construction overhead.
Common use cases: temporal joins (event → time window), financial tier lookups (amount → price range), SCD joins.
What changes are included in this PR?
IntervalJoinExec(physical-plan/src/joins/interval_join.rs): sort-merge range join operator for inner joinswith point-in-interval pattern. Collects + sorts build side by low bound, sorts each probe batch internally, uses a
monotonic boundary pointer for amortized O(1) per-probe-row matching.
core/src/physical_planner.rs): detectsprobe_col {>= | >} build_low AND probe_col {< | <=} build_highin the non-equi join path. Handles flipped operands and reordered conditions. Falls through to NLJ ifpattern doesn't match.
common/src/config.rs):datafusion.optimizer.enable_interval_join(defaulttrue).interval_join.slt): basic matching, edge cases (empty sides, NULLs, overlapping intervals, boundaryinclusivity), EXPLAIN plan verification, timestamp + interval arithmetic.
join_fuzz.rs): compares IntervalJoinExec output against NLJ for correctness with random data.Are these changes tested?
Yes:
operators, EXPLAIN output, and timestamp types
Are there any user-facing changes?
No