Skip to content

Extend dynamic filter to joins that preserve probe side ON#20447

Merged
adriangb merged 1 commit intoapache:mainfrom
helgikrs:left-join-filter-pushdown
Mar 2, 2026
Merged

Extend dynamic filter to joins that preserve probe side ON#20447
adriangb merged 1 commit intoapache:mainfrom
helgikrs:left-join-filter-pushdown

Conversation

@helgikrs
Copy link
Contributor

@helgikrs helgikrs commented Feb 20, 2026

The dynamic filter from HashJoinExec was previously gated to Inner joins only.

PR #20192 refactored the join filter pushdown infrastructure, which makes extending self-generated filters to join types that preserve probe side on as defined by by on_lr_is_preserved function trivial.

This PR promotes that function to the JoinType and uses it to determine what self-generated dynamic join filter to push down.

This enables dynamic filter for hash joins to Left, LeftSemi, RightSemi, LeftAnti and LeftMark.

Which issue does this PR close?

This PR makes progress on #16973

Rationale for this change

The self-generated dynamic filter in HashJoinExec filters the probe side using build-side values. For Left and LeftSemi joins, the right-hand probe side has the same filtering semantics as Inner. Relaxing the gate using on_lr_is_preserved.

Are these changes tested?

Yes.

Are there any user-facing changes?

No.

@github-actions github-actions bot added core Core DataFusion crate sqllogictest SQL Logic Tests (.slt) physical-plan Changes to the physical-plan crate labels Feb 20, 2026

fn allow_join_dynamic_filter_pushdown(&self, config: &ConfigOptions) -> bool {
if self.join_type != JoinType::Inner
if !matches!(self.join_type, JoinType::Inner | JoinType::Left | JoinType::LeftSemi)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can JoinType::Right and JoinType::RightSemi also be applied based on the same rationale?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think so. The build side is always the left side and the probe side is always the right side. The filters are therefore always pushed to the right side. We need to retain all rows from the right side for a Right join, so there's nothing we can push down.

A right join query can still take advantage of this if the the optimizer decides to swap the sides to build the right side to the join, in that case it would become a left join here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually I think it might be safe to add RightSemi and LeftAnti to this list.

The dynamic filter only removes probe rows that can't match any build row, and neither RightSemi (which outputs only matched probe rows) nor LeftAnti (which outputs only unmatched build rows) includes unmatched probe rows in its output. So I think it would be safe to add those here as well. Right and RightAnti would not be.

@helgikrs helgikrs force-pushed the left-join-filter-pushdown branch from 7cf1bc6 to 4e40891 Compare February 20, 2026 16:18
@helgikrs helgikrs force-pushed the left-join-filter-pushdown branch 2 times, most recently from 0dac298 to 1ea0252 Compare February 22, 2026 11:10
Copy link
Contributor

@jonathanc-n jonathanc-n left a comment

Choose a reason for hiding this comment

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

Thanks, one step closer!

@jonathanc-n
Copy link
Contributor

cc @adriangb @nuno-faria

@nuno-faria
Copy link
Contributor

Thanks @helgikrs, all tests have passed. I'll try to review it carefully tomorrow.

Copy link
Contributor

@nuno-faria nuno-faria left a comment

Choose a reason for hiding this comment

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

LGTM, I couldn't find an edge case where it fails. I think other join types can also be added, but this can be done in a future PR.

Comment on lines +741 to +744
if !matches!(
self.join_type,
JoinType::Inner | JoinType::Left | JoinType::LeftSemi
) || !config.optimizer.enable_join_dynamic_filter_pushdown
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would also work with LeftAnti, but it doesn't need to be included in this PR.

Also, it would be interesting to explore RightSemi as well, since some queries will opt to use it if the statistics are not accurate. For example:

-- t1 >> t2

-- uses LeftSemi: dynamic filter added
select *
from t1
where t1.k in (select k from t2)
    and t1.v2 in (123);

-- uses RightSemi: no dynamic filter
select *
from t1
where t1.k in (select k from t2)
    and t1.v2 in (123, 456);

Once again, both cases can be considered in a future PR.

@nuno-faria
Copy link
Contributor

@adriangb please take a look as well if you have the chance.

Copy link
Contributor

@adriangb adriangb left a comment

Choose a reason for hiding this comment

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

Looks good to me!

I wonder - should we use on_lr_is_preserved to determine what is safe or not?

@helgikrs helgikrs force-pushed the left-join-filter-pushdown branch from d411d39 to dde27fc Compare February 27, 2026 16:23
@adriangb
Copy link
Contributor

adriangb commented Feb 27, 2026

Looks good to me!

I wonder - should we use on_lr_is_preserved to determine what is safe or not?

@helgikrs I don't think it's required for this PR, we can merge it as is but curious to get your thoughts about on_lr_is_preserved?

@helgikrs
Copy link
Contributor Author

Looks good to me!
I wonder - should we use on_lr_is_preserved to determine what is safe or not?

@helgikrs I don't think it's required for this PR, we can merge it as is but curious to get your thoughts about on_lr_is_preserved?

I considered that, and I think that would definitely make sense, it captures the safety semantics we'd want. The practical consideration is just that it's currently is pub(crate) in the optimizer crate, so I think we'd have to move it to expose it to the physical-plan crate. It might maybe make sense as a function on the JoinType?

@adriangb
Copy link
Contributor

Looks good to me!
I wonder - should we use on_lr_is_preserved to determine what is safe or not?

@helgikrs I don't think it's required for this PR, we can merge it as is but curious to get your thoughts about on_lr_is_preserved?

I considered that, and I think that would definitely make sense, it captures the safety semantics we'd want. The practical consideration is just that it's currently is pub(crate) in the optimizer crate, so I think we'd have to move it to expose it to the physical-plan crate. It might maybe make sense as a function on the JoinType?

That seems like a nice cleanup to me.

@helgikrs helgikrs force-pushed the left-join-filter-pushdown branch from dde27fc to e9c406c Compare February 28, 2026 10:11
@github-actions github-actions bot added optimizer Optimizer rules common Related to common crate labels Feb 28, 2026
@helgikrs helgikrs changed the title Extend dynamic filter pushdown to Left and LeftSemi hash joins Extend dynamic filter to joins that preserve probe side ON Feb 28, 2026
The dynamic filter from HashJoinExec was previously gated to Inner joins
only.

PR apache#20192 refactored the join filter pushdown infrastructure, which
makes extending self-generated filters to join types that preserve probe
side on as defined by by `on_lr_is_preserved` function.

This PR promotes that function to the `JoinType` and uses it to
determine what self-generated dynamic join filter to push down.

This enables dynamic filter for hash joins to Left, LeftSemi, RightSemi,
LeftAnti and LeftMark.
@helgikrs helgikrs force-pushed the left-join-filter-pushdown branch from e9c406c to c680f0d Compare February 28, 2026 10:13
@helgikrs
Copy link
Contributor Author

helgikrs commented Feb 28, 2026

@adriangb moved on_lr_is_preserved to the JoinType and updated the gate to use that function, updated and added some more tests to reflect that change as well. Now, with this change, the dynamic filter would be pushed down for Left, LeftSemi, RightSemi, LeftAnti and LeftMark joins.

@adriangb
Copy link
Contributor

Thank you @helgikrs!

@nuno-faria how do you feel about testing? On the one hand we are now using a well tested logic for when it is safe to push down join clause filters. On the other hand I am hesitant to merge this without tests. I personally feel it would be nice to have join fuzz tests that verify that with / without dynamic filters results are the same. But that would be a big change that delays this PR, I don't want to block it. One thing we could do is wait until the 53 release branch is cut (next week or so I think) and merge this after, so we at least have a month to fix any bugs. But if you are confident this is correct then I'm also happy to merge it as is. Wdyt?

@nuno-faria
Copy link
Contributor

I personally feel it would be nice to have join fuzz tests that verify that with / without dynamic filters results are the same.

100% agreed.

One thing we could do is wait until the 53 release branch is cut (next week or so I think) and merge this after, so we at least have a month to fix any bugs.

Yeah it might be better to wait just to be safe.

I am curious about what we would be missing out on DF53. @alamb is it possible to run the tpc-ds queries against this PR?

@adriangb
Copy link
Contributor

run benchmark tpcds

@adriangb
Copy link
Contributor

run benchmark tpcds
DATAFUSION_EXECUTION_PARQUET_PUSHDOWN_FILTERS=true
DATAFUSION_EXECUTION_PARQUET_REORDER_FILTERS=true

@alamb-ghbot
Copy link

🤖 ./gh_compare_branch.sh gh_compare_branch.sh Running
Linux aal-dev 6.14.0-1018-gcp #19~24.04.1-Ubuntu SMP Wed Sep 24 23:23:09 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
Comparing left-join-filter-pushdown (c680f0d) to acec058 diff using: tpcds
Results will be posted here when complete

@alamb-ghbot
Copy link

🤖: Benchmark completed

Details

Comparing HEAD and left-join-filter-pushdown
--------------------
Benchmark tpcds_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃        HEAD ┃ left-join-filter-pushdown ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 1  │    71.86 ms │                  73.91 ms │     no change │
│ QQuery 2  │   206.54 ms │                 207.49 ms │     no change │
│ QQuery 3  │   151.11 ms │                 151.27 ms │     no change │
│ QQuery 4  │  1850.11 ms │                1807.55 ms │     no change │
│ QQuery 5  │   261.57 ms │                 252.00 ms │     no change │
│ QQuery 6  │  1455.06 ms │                1433.75 ms │     no change │
│ QQuery 7  │   503.97 ms │                 509.01 ms │     no change │
│ QQuery 8  │   167.31 ms │                 164.96 ms │     no change │
│ QQuery 9  │   293.86 ms │                 278.35 ms │ +1.06x faster │
│ QQuery 10 │   174.86 ms │                 167.99 ms │     no change │
│ QQuery 11 │  1247.45 ms │                1239.15 ms │     no change │
│ QQuery 12 │    65.38 ms │                  66.55 ms │     no change │
│ QQuery 13 │   533.78 ms │                 528.08 ms │     no change │
│ QQuery 14 │  1843.77 ms │                1874.20 ms │     no change │
│ QQuery 15 │    27.25 ms │                  27.68 ms │     no change │
│ QQuery 16 │    62.42 ms │                  63.35 ms │     no change │
│ QQuery 17 │   346.71 ms │                 352.48 ms │     no change │
│ QQuery 18 │   192.63 ms │                 194.56 ms │     no change │
│ QQuery 19 │   211.80 ms │                 211.09 ms │     no change │
│ QQuery 20 │    25.85 ms │                  24.19 ms │ +1.07x faster │
│ QQuery 21 │    36.20 ms │                  36.22 ms │     no change │
│ QQuery 22 │   708.33 ms │                 707.47 ms │     no change │
│ QQuery 23 │  1727.92 ms │                1733.07 ms │     no change │
│ QQuery 24 │   687.61 ms │                 679.00 ms │     no change │
│ QQuery 25 │   518.13 ms │                 515.51 ms │     no change │
│ QQuery 26 │   125.57 ms │                 125.95 ms │     no change │
│ QQuery 27 │   504.25 ms │                 498.52 ms │     no change │
│ QQuery 28 │   292.64 ms │                 282.14 ms │     no change │
│ QQuery 29 │   441.52 ms │                 440.81 ms │     no change │
│ QQuery 30 │    73.91 ms │                  76.17 ms │     no change │
│ QQuery 31 │   293.62 ms │                 302.13 ms │     no change │
│ QQuery 32 │    80.30 ms │                  80.30 ms │     no change │
│ QQuery 33 │   201.48 ms │                 202.34 ms │     no change │
│ QQuery 34 │   156.64 ms │                 156.84 ms │     no change │
│ QQuery 35 │   167.07 ms │                 168.03 ms │     no change │
│ QQuery 36 │   284.27 ms │                 277.36 ms │     no change │
│ QQuery 37 │   256.80 ms │                 257.02 ms │     no change │
│ QQuery 38 │   148.01 ms │                 156.58 ms │  1.06x slower │
│ QQuery 39 │   195.90 ms │                 193.70 ms │     no change │
│ QQuery 40 │   177.84 ms │                 181.81 ms │     no change │
│ QQuery 41 │    25.33 ms │                  26.37 ms │     no change │
│ QQuery 42 │   141.13 ms │                 138.60 ms │     no change │
│ QQuery 43 │   123.91 ms │                 122.60 ms │     no change │
│ QQuery 44 │    27.59 ms │                  27.78 ms │     no change │
│ QQuery 45 │    84.36 ms │                  85.53 ms │     no change │
│ QQuery 46 │   315.28 ms │                 313.28 ms │     no change │
│ QQuery 47 │   994.23 ms │                 988.11 ms │     no change │
│ QQuery 48 │   396.34 ms │                 393.13 ms │     no change │
│ QQuery 49 │   370.45 ms │                 361.95 ms │     no change │
│ QQuery 50 │   319.01 ms │                 329.92 ms │     no change │
│ QQuery 51 │   301.58 ms │                 296.56 ms │     no change │
│ QQuery 52 │   142.04 ms │                 140.90 ms │     no change │
│ QQuery 53 │   144.33 ms │                 141.88 ms │     no change │
│ QQuery 54 │   197.67 ms │                 195.70 ms │     no change │
│ QQuery 55 │   140.85 ms │                 138.84 ms │     no change │
│ QQuery 56 │   202.52 ms │                 200.51 ms │     no change │
│ QQuery 57 │   285.58 ms │                 283.59 ms │     no change │
│ QQuery 58 │   497.22 ms │                 495.39 ms │     no change │
│ QQuery 59 │   285.29 ms │                 284.44 ms │     no change │
│ QQuery 60 │   211.61 ms │                 207.29 ms │     no change │
│ QQuery 61 │   242.34 ms │                 239.73 ms │     no change │
│ QQuery 62 │  1281.67 ms │                1272.74 ms │     no change │
│ QQuery 63 │   145.17 ms │                 143.43 ms │     no change │
│ QQuery 64 │  1147.79 ms │                1124.34 ms │     no change │
│ QQuery 65 │   343.90 ms │                 341.48 ms │     no change │
│ QQuery 66 │   384.58 ms │                 376.04 ms │     no change │
│ QQuery 67 │   535.14 ms │                 516.17 ms │     no change │
│ QQuery 68 │   368.13 ms │                 362.90 ms │     no change │
│ QQuery 69 │   167.22 ms │                 166.22 ms │     no change │
│ QQuery 70 │   478.29 ms │                 481.77 ms │     no change │
│ QQuery 71 │   181.97 ms │                 180.09 ms │     no change │
│ QQuery 72 │  2094.21 ms │                2120.83 ms │     no change │
│ QQuery 73 │   151.76 ms │                 150.47 ms │     no change │
│ QQuery 74 │   785.98 ms │                 781.16 ms │     no change │
│ QQuery 75 │   404.37 ms │                 396.91 ms │     no change │
│ QQuery 76 │   184.83 ms │                 182.07 ms │     no change │
│ QQuery 77 │   279.10 ms │                 272.77 ms │     no change │
│ QQuery 78 │   596.13 ms │                 586.30 ms │     no change │
│ QQuery 79 │   315.43 ms │                 312.48 ms │     no change │
│ QQuery 80 │   510.75 ms │                 506.64 ms │     no change │
│ QQuery 81 │    54.44 ms │                  52.11 ms │     no change │
│ QQuery 82 │   275.14 ms │                 277.75 ms │     no change │
│ QQuery 83 │    79.36 ms │                  74.69 ms │ +1.06x faster │
│ QQuery 84 │    69.14 ms │                  67.36 ms │     no change │
│ QQuery 85 │   224.79 ms │                 210.37 ms │ +1.07x faster │
│ QQuery 86 │    57.48 ms │                  57.78 ms │     no change │
│ QQuery 87 │   151.68 ms │                 151.23 ms │     no change │
│ QQuery 88 │   249.43 ms │                 249.63 ms │     no change │
│ QQuery 89 │   163.09 ms │                 162.06 ms │     no change │
│ QQuery 90 │    45.80 ms │                  44.17 ms │     no change │
│ QQuery 91 │    98.10 ms │                  93.91 ms │     no change │
│ QQuery 92 │    79.95 ms │                  79.68 ms │     no change │
│ QQuery 93 │   288.25 ms │                 285.95 ms │     no change │
│ QQuery 94 │    89.75 ms │                  90.90 ms │     no change │
│ QQuery 95 │   241.31 ms │                 241.50 ms │     no change │
│ QQuery 96 │   109.65 ms │                 108.97 ms │     no change │
│ QQuery 97 │   187.41 ms │                 185.94 ms │     no change │
│ QQuery 98 │   214.86 ms │                 212.29 ms │     no change │
│ QQuery 99 │ 14223.68 ms │               14217.68 ms │     no change │
└───────────┴─────────────┴───────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                        ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                        │ 49479.70ms │
│ Total Time (left-join-filter-pushdown)   │ 49249.45ms │
│ Average Time (HEAD)                      │   499.79ms │
│ Average Time (left-join-filter-pushdown) │   497.47ms │
│ Queries Faster                           │          4 │
│ Queries Slower                           │          1 │
│ Queries with No Change                   │         94 │
│ Queries with Failure                     │          0 │
└──────────────────────────────────────────┴────────────┘

@alamb-ghbot
Copy link

🤖 ./gh_compare_branch.sh gh_compare_branch.sh Running
Linux aal-dev 6.14.0-1018-gcp #19~24.04.1-Ubuntu SMP Wed Sep 24 23:23:09 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
Comparing left-join-filter-pushdown (c680f0d) to acec058 diff using: tpcds
Results will be posted here when complete

@alamb-ghbot
Copy link

🤖: Benchmark completed

Details

Comparing HEAD and left-join-filter-pushdown
--------------------
Benchmark tpcds_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃        HEAD ┃ left-join-filter-pushdown ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 1  │    83.85 ms │                  86.31 ms │     no change │
│ QQuery 2  │   240.56 ms │                 240.35 ms │     no change │
│ QQuery 3  │   155.61 ms │                 159.10 ms │     no change │
│ QQuery 4  │  1572.46 ms │                1571.92 ms │     no change │
│ QQuery 5  │   300.48 ms │                 292.20 ms │     no change │
│ QQuery 6  │   418.94 ms │                 413.44 ms │     no change │
│ QQuery 7  │   524.08 ms │                 534.62 ms │     no change │
│ QQuery 8  │   247.10 ms │                 239.35 ms │     no change │
│ QQuery 9  │   864.12 ms │                 879.19 ms │     no change │
│ QQuery 10 │   273.78 ms │                 270.78 ms │     no change │
│ QQuery 11 │  1009.45 ms │                 993.92 ms │     no change │
│ QQuery 12 │    57.25 ms │                  55.42 ms │     no change │
│ QQuery 13 │   845.99 ms │                 843.68 ms │     no change │
│ QQuery 14 │  1810.66 ms │                1801.85 ms │     no change │
│ QQuery 15 │    31.92 ms │                  32.51 ms │     no change │
│ QQuery 16 │    63.64 ms │                  67.59 ms │  1.06x slower │
│ QQuery 17 │   292.47 ms │                 294.50 ms │     no change │
│ QQuery 18 │   487.63 ms │                 478.92 ms │     no change │
│ QQuery 19 │   189.58 ms │                 188.54 ms │     no change │
│ QQuery 20 │    25.43 ms │                  27.04 ms │  1.06x slower │
│ QQuery 21 │    49.06 ms │                  48.48 ms │     no change │
│ QQuery 22 │   738.14 ms │                 739.86 ms │     no change │
│ QQuery 23 │  2414.06 ms │                2121.49 ms │ +1.14x faster │
│ QQuery 24 │   247.52 ms │                 253.07 ms │     no change │
│ QQuery 25 │   437.31 ms │                 440.83 ms │     no change │
│ QQuery 26 │   278.30 ms │                 276.30 ms │     no change │
│ QQuery 27 │   525.92 ms │                 526.33 ms │     no change │
│ QQuery 28 │   492.15 ms │                 506.36 ms │     no change │
│ QQuery 29 │   377.44 ms │                 383.21 ms │     no change │
│ QQuery 30 │    91.28 ms │                  90.75 ms │     no change │
│ QQuery 31 │   301.84 ms │                 288.64 ms │     no change │
│ QQuery 32 │    77.00 ms │                  75.86 ms │     no change │
│ QQuery 33 │   190.41 ms │                 187.63 ms │     no change │
│ QQuery 34 │   194.81 ms │                 196.56 ms │     no change │
│ QQuery 35 │   247.15 ms │                 246.81 ms │     no change │
│ QQuery 36 │   348.53 ms │                 346.66 ms │     no change │
│ QQuery 37 │   972.15 ms │                 957.84 ms │     no change │
│ QQuery 38 │   176.16 ms │                 168.65 ms │     no change │
│ QQuery 39 │   205.29 ms │                 213.27 ms │     no change │
│ QQuery 40 │   216.60 ms │                 211.02 ms │     no change │
│ QQuery 41 │    26.72 ms │                  25.61 ms │     no change │
│ QQuery 42 │   144.47 ms │                 144.51 ms │     no change │
│ QQuery 43 │   168.24 ms │                 167.35 ms │     no change │
│ QQuery 44 │    27.56 ms │                  27.57 ms │     no change │
│ QQuery 45 │    69.55 ms │                  70.86 ms │     no change │
│ QQuery 46 │   316.21 ms │                 310.33 ms │     no change │
│ QQuery 47 │  1185.76 ms │                1195.09 ms │     no change │
│ QQuery 48 │   706.49 ms │                 703.00 ms │     no change │
│ QQuery 49 │   392.56 ms │                 385.09 ms │     no change │
│ QQuery 50 │   720.96 ms │                 723.85 ms │     no change │
│ QQuery 51 │   356.01 ms │                 356.68 ms │     no change │
│ QQuery 52 │   145.53 ms │                 145.34 ms │     no change │
│ QQuery 53 │   212.99 ms │                 205.89 ms │     no change │
│ QQuery 54 │   184.31 ms │                 185.76 ms │     no change │
│ QQuery 55 │   149.08 ms │                 141.90 ms │     no change │
│ QQuery 56 │   191.76 ms │                 192.44 ms │     no change │
│ QQuery 57 │   303.34 ms │                 306.38 ms │     no change │
│ QQuery 58 │   593.87 ms │                 602.13 ms │     no change │
│ QQuery 59 │   355.57 ms │                 358.77 ms │     no change │
│ QQuery 60 │   202.71 ms │                 203.02 ms │     no change │
│ QQuery 61 │   265.30 ms │                 259.84 ms │     no change │
│ QQuery 62 │  1287.12 ms │                1288.74 ms │     no change │
│ QQuery 63 │   210.65 ms │                 207.80 ms │     no change │
│ QQuery 64 │ 29355.65 ms │               28975.92 ms │     no change │
│ QQuery 65 │   424.81 ms │                 422.21 ms │     no change │
│ QQuery 66 │   281.90 ms │                 284.44 ms │     no change │
│ QQuery 67 │   830.52 ms │                 817.79 ms │     no change │
│ QQuery 68 │   334.52 ms │                 334.72 ms │     no change │
│ QQuery 69 │   272.23 ms │                 271.21 ms │     no change │
│ QQuery 70 │   649.16 ms │                 643.41 ms │     no change │
│ QQuery 71 │   175.86 ms │                 175.79 ms │     no change │
│ QQuery 72 │  1782.70 ms │                1778.81 ms │     no change │
│ QQuery 73 │   172.53 ms │                 177.41 ms │     no change │
│ QQuery 74 │   722.78 ms │                 725.81 ms │     no change │
│ QQuery 75 │   441.26 ms │                 439.22 ms │     no change │
│ QQuery 76 │   385.02 ms │                 390.21 ms │     no change │
│ QQuery 77 │   333.52 ms │                 335.10 ms │     no change │
│ QQuery 78 │   518.80 ms │                 518.17 ms │     no change │
│ QQuery 79 │   367.35 ms │                 369.32 ms │     no change │
│ QQuery 80 │   441.32 ms │                 452.87 ms │     no change │
│ QQuery 81 │    58.00 ms │                  58.43 ms │     no change │
│ QQuery 82 │   254.17 ms │                 257.81 ms │     no change │
│ QQuery 83 │   106.58 ms │                  80.63 ms │ +1.32x faster │
│ QQuery 84 │    96.76 ms │                  98.41 ms │     no change │
│ QQuery 85 │   419.05 ms │                 422.59 ms │     no change │
│ QQuery 86 │    70.79 ms │                  72.56 ms │     no change │
│ QQuery 87 │   180.23 ms │                 175.23 ms │     no change │
│ QQuery 88 │   311.42 ms │                 311.29 ms │     no change │
│ QQuery 89 │   233.37 ms │                 241.17 ms │     no change │
│ QQuery 90 │    50.40 ms │                  49.88 ms │     no change │
│ QQuery 91 │   142.70 ms │                 148.60 ms │     no change │
│ QQuery 92 │    75.09 ms │                  74.50 ms │     no change │
│ QQuery 93 │   279.28 ms │                 284.46 ms │     no change │
│ QQuery 94 │    93.07 ms │                  92.67 ms │     no change │
│ QQuery 95 │   306.22 ms │                 201.12 ms │ +1.52x faster │
│ QQuery 96 │   129.04 ms │                 117.07 ms │ +1.10x faster │
│ QQuery 97 │   236.32 ms │                 233.13 ms │     no change │
│ QQuery 98 │   157.69 ms │                 164.00 ms │     no change │
│ QQuery 99 │ 14234.36 ms │               14283.45 ms │     no change │
└───────────┴─────────────┴───────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                        ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                        │ 81217.34ms │
│ Total Time (left-join-filter-pushdown)   │ 80438.24ms │
│ Average Time (HEAD)                      │   820.38ms │
│ Average Time (left-join-filter-pushdown) │   812.51ms │
│ Queries Faster                           │          4 │
│ Queries Slower                           │          2 │
│ Queries with No Change                   │         93 │
│ Queries with Failure                     │          0 │
└──────────────────────────────────────────┴────────────┘

@adriangb
Copy link
Contributor

adriangb commented Mar 2, 2026

I personally feel it would be nice to have join fuzz tests that verify that with / without dynamic filters results are the same.

100% agreed.

One thing we could do is wait until the 53 release branch is cut (next week or so I think) and merge this after, so we at least have a month to fix any bugs.

Yeah it might be better to wait just to be safe.

I am curious about what we would be missing out on DF53. @alamb is it possible to run the tpc-ds queries against this PR?

The v53 branch has been cut, so I think we can go ahead and merge this and target v54.

@helgikrs would you be able to help us build some join fuzz tests in the meantime?

@adriangb adriangb added this pull request to the merge queue Mar 2, 2026
Merged via the queue into apache:main with commit 93d177d Mar 2, 2026
34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

common Related to common crate core Core DataFusion crate optimizer Optimizer rules physical-plan Changes to the physical-plan crate sqllogictest SQL Logic Tests (.slt)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants