Repository navigation
Commit ed22a4a
Gustavo Schneiter
feat: support co-partitioned range right-side equi hash joins (#23484)
## Which issue does this PR close?
- Closes #23453.
- Part of #22395.
## Rationale for this change
#23184 let compatible range-partitioned inputs satisfy **inner**
partitioned hash joins without repartitioning. Right-side partitioned
equi joins have the same locality guarantee: `Right`, `RightSemi`,
`RightAnti` and `RightMark` all anchor every output row on the probe
(right) partition (`on_lr_is_preserved` is probe-side for all four), so
when both inputs are co-partitioned by the join keys, execution stays
partition-local and the hash repartition is unnecessary.
This removes unnecessary `RepartitionExec`s for already-co-located
inputs, extending the inner-join behavior from #23184 to the right-side
variants. No micro-benchmark included, consistent with #23184;
correctness is demonstrated by matched/unmatched execution results
below.
## What changes are included in this PR?
The only production change is widening the existing inner-only gate in
`HashJoinExec::input_distribution_requirements` from `join_type ==
JoinType::Inner` to `matches!(join_type, Inner | Right | RightSemi |
RightAnti | RightMark)` (under `PartitionMode::Partitioned`). The
`co_partitioned` / range-satisfaction machinery from #23184 is unchanged
— the sanity checker and enforce_distribution consume range satisfaction
join-type-agnostically.
One behavior note for #23376: range co-partitioned right joins now stay
`Range`/`Range`, so partitioned dynamic filters are disabled for them
(`has_partitioned_dynamic_filter_routing` returns false), the same safe
delta #23184 introduced for inner joins. These variants are
probe-not-preserved for pruning, so dynamic filters were not eligible to
prune their probe rows regardless.
## Are these changes tested?
Yes.
- Optimizer (`enforce_distribution.rs`): 4 reuse tests (one per join
type) proving compatible range/range inputs keep `Range` partitioning
with no `RepartitionExec`; 4 incompatibility tests proving that
mismatched split points, sort options, partition counts, or join-key
expressions still insert a hash repartition; sanity-check pairs
mirroring #23184.
- Execution (`range_partitioning.slt`): `EXPLAIN` plan pins plus
matched/unmatched result checks for `Right` (incl. `NULL` left values),
`RightSemi`, `RightAnti`, and an incompatible-layout `Right` join
(repartitions, correct results).
- The new reuse tests fail on `main` without the gate change (verified
by reverting the production diff: exactly the 4 reuse tests fail,
everything else passes).
- `RightMark` testing note: `RightMark` is not reachable from SQL in
sqllogictest (`IN`-subquery decorrelation emits `LeftMark`; physical
`RightMark` only appears via a statistics-based swap), so its
co-partitioning behavior is pinned at the optimizer/plan level, and mark
null-marker semantics (matched/unmatched/`NULL` build keys) are pinned
via the `LeftMark` path in the slt.
## Are there any user-facing changes?
No API changes. Plans over compatible range-partitioned inputs avoid a
hash repartition for right-side equi hash joins.1 parent 9a50c67 commit ed22a4a
5 files changed
Lines changed: 449 additions & 26 deletions
File tree
- datafusion
- core/tests/physical_optimizer
- physical-plan/src/joins/hash_join
- sqllogictest
- src/test_context
- test_files
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
870 | 870 | | |
871 | 871 | | |
872 | 872 | | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
| 892 | + | |
| 893 | + | |
| 894 | + | |
| 895 | + | |
| 896 | + | |
| 897 | + | |
| 898 | + | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
873 | 946 | | |
874 | 947 | | |
875 | 948 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
445 | 445 | | |
446 | 446 | | |
447 | 447 | | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
448 | 474 | | |
449 | 475 | | |
450 | 476 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1294 | 1294 | | |
1295 | 1295 | | |
1296 | 1296 | | |
1297 | | - | |
| 1297 | + | |
| 1298 | + | |
| 1299 | + | |
| 1300 | + | |
| 1301 | + | |
| 1302 | + | |
| 1303 | + | |
| 1304 | + | |
| 1305 | + | |
1298 | 1306 | | |
1299 | 1307 | | |
1300 | 1308 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
131 | 131 | | |
132 | 132 | | |
133 | 133 | | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
134 | 162 | | |
135 | 163 | | |
136 | 164 | | |
| |||
0 commit comments