Skip to content

Conversation

rkrishn7
Copy link
Contributor

@rkrishn7 rkrishn7 commented Sep 11, 2025

Which issue does this PR close?

What changes are included in this PR?

  • Adds a new configuration option (hash_join_sideways_hash_passing) to enable passing hashes from build side to probe side scans.
  • Adds a new internal HashComparePhysicalExpr that is pushed down to supported right-side scans in hash join.

Are these changes tested?

Not yet. Plan to add unit + fuzz tests

Are there any user-facing changes?

Yes, new configuration option for hash join execution.

@github-actions github-actions bot added sqllogictest SQL Logic Tests (.slt) common Related to common crate execution Related to the execution crate physical-plan Changes to the physical-plan crate labels Sep 11, 2025
@rkrishn7 rkrishn7 force-pushed the feat/pushdown-hashes-hashjoinexec branch from 0649ad3 to 18d2acc Compare September 16, 2025 21:22
@github-actions github-actions bot added the documentation Improvements or additions to documentation label Sep 16, 2025
@rkrishn7 rkrishn7 force-pushed the feat/pushdown-hashes-hashjoinexec branch from 131c4c5 to 8c5d61b Compare September 16, 2025 21:50
@rkrishn7 rkrishn7 force-pushed the feat/pushdown-hashes-hashjoinexec branch from 8c5d61b to e23fbea Compare September 16, 2025 21:51
@rkrishn7 rkrishn7 marked this pull request as ready for review September 16, 2025 22:40
//! ```
//! The join portion of the query should look something like this:
//!
//! ```text
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @alamb for the diagrams 😄 (from #7955)

@rkrishn7 rkrishn7 changed the title feat: pushdown hashes hashjoinexec feat: pushdown hashes to probe side in HashJoinExec Sep 16, 2025
@rkrishn7 rkrishn7 changed the title feat: pushdown hashes to probe side in HashJoinExec feat: Push down hashes to probe side in HashJoinExec Sep 16, 2025
@rkrishn7
Copy link
Contributor Author

@adriangb I think this is probably ready for an initial look when you get a chance! I plan on adding unit + fuzz tests as well. But let me know if you have any other thoughts re: testing.

@rkrishn7
Copy link
Contributor Author

@alamb Would you be able to kick off benchmarks 🙏🏾 ? Specifically TPC-H against parquet files

Should want the following configuration options set:

DATAFUSION_EXECUTION_HASH_JOIN_SIDEWAYS_HASH_PASSING=true
DATAFUSION_EXECUTION_PARQUET_PUSHDOWN_FILTERS=true

/// Each element represents the column bounds computed by one partition.
bounds: Vec<PartitionBounds>,
/// Hashes from the left (build) side, if enabled
left_hashes: NoHashSet<u64>,
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 found using a HashSet here to yield better performance than using a Vec<Arc<dyn JoinHashMapType>>. Though, it does of course result in extra allocations.

My guess is that its primarily due to that Vec<Arc<dyn JoinHashMapType>> results in more indirection + scattered memory accesses which likely means worse cache locality.

Copy link
Contributor

Choose a reason for hiding this comment

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

I worry that the extra memory cost is prohibitively expensive: there are going to be queries that ran just fine previously but now OOM.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since this is opt-in, hopefully it's not as much of an issue? I've mentioned this in the config documentation:

/// When set to true, hash joins will allow passing hashes from the build
/// side to the right side of the join. This can be useful to prune rows early on,
/// but may consume more memory.

In general though I agree that we shouldn't need extra allocations here. It gets a bit tricky though because even if we combine all the hash tables from each build partition into a single, shareable table - each stream probe partition needs to be able to validate that the lookup is localized to its partition. Otherwise we'll see duplicate / incorrect results I believe.

Though, it may just take some tweaking to the existing data structure. Haven't thought about it enough.

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 the way you'd do it is something like (col in hash_table_1) OR (col in hash_table_2) OR (...)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yeah that's essentially the same as what I was referring to earlier with using a Vec<Arc<dyn JoinHashMapType>> (sorry probably should've clarified more).

Copy link
Contributor

Choose a reason for hiding this comment

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

👋 I'd be happy to test this in our service, and see memory implications in a prod environment. I guess for any query that uses this kind of filter, the Hash table shouldn't be big? otherwise this kind of filters wont be that worth it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi @LiaCastaneda - that would be great! And apologies for the delayed response.

I am curious to see how gains diminish as the build side grows larger. I'm not sure if it is that drastic or if there are still gains to be seen for very large build sides. To me the biggest downside is memory usage. e.g. a build side with 1 billion hashes would be ~8GB of additional memory.

Currently there are no checks to determine whether it is worth it to build the hash set and push it down. Though, that could be done via separate configuration depending on the upper bound of memory consumption a consumer is comfortable with for this feature 🤔

Copy link
Contributor

@LiaCastaneda LiaCastaneda Oct 8, 2025

Choose a reason for hiding this comment

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

That makes sense, our current plan for using this API is to use some available statistics we have ( like row count), and set the enable_dynamic... option based on that, so its even before logical and physical DataFusion planning. Would it be possible to do something similar in DataFusion itself while running the optimizer rule?
Although the option you mention is more straightforward, are you suggesting that we set a configuration option for maximum memory consumption and, when building the hashes, stop producing them and free memory if we exceed that limit?

}

impl SharedBuildAccumulator {
/// Creates a new [SharedBuildAccumulator] configured for the given partition mode
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Creates a new [SharedBuildAccumulator] configured for the given partition mode
/// Creates a new [`SharedBuildAccumulator`] configured for the given partition mode

@adriangb
Copy link
Contributor

Very cool!

Incidentally we were just discussing today with @gabotechs and @robtandy how to make HashJoin dynamic filter pushdown more compatible with distributed datafusion and how to eliminate the latency associated with waiting until we have the full build side to create filters.

One idea that came up was to push something like:
(hash(join_key_col) % parts != 0) or join_key_col >= 1 and join_key_col <= 2 where 0 is the partition number, 1 is the min val for join_key_col in that partition and 2 is the max val
We can push these down "as they are ready" and then once the all partitions are ready we can simplify this to our current join_key_col >= 1 and join_key_col <= 2.
I bring this up because the main sticking point with that approach is that we add third computation of the hash to the existing two (in the hash join and repartition/shuffle), which might have a performance impact.
That led us to file #17599 which is a broader issue that DataFusion has.

But for this PR the big question in my mind is going to be: is the cost of the extra evaluation of the hash worth it?

@alamb
Copy link
Contributor

alamb commented Sep 17, 2025

🤖 ./gh_compare_branch.sh Benchmark Script Running
Linux aal-dev 6.14.0-1014-gcp #15~24.04.1-Ubuntu SMP Fri Jul 25 23:26:08 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
Comparing feat/pushdown-hashes-hashjoinexec (76e0c0a) to 0181c79 diff using: tpch_mem clickbench_partitioned clickbench_extended
Results will be posted here when complete

@alamb
Copy link
Contributor

alamb commented Sep 17, 2025

@alamb Would you be able to kick off benchmarks 🙏🏾 ? Specifically TPC-H against parquet files

Should want the following configuration options set:

DATAFUSION_EXECUTION_HASH_JOIN_SIDEWAYS_HASH_PASSING=true
DATAFUSION_EXECUTION_PARQUET_PUSHDOWN_FILTERS=true

I am not quite sure how to set these options in the benchmarks...

@rkrishn7
Copy link
Contributor Author

@alamb Would you be able to kick off benchmarks 🙏🏾 ? Specifically TPC-H against parquet files
Should want the following configuration options set:

DATAFUSION_EXECUTION_HASH_JOIN_SIDEWAYS_HASH_PASSING=true
DATAFUSION_EXECUTION_PARQUET_PUSHDOWN_FILTERS=true

I am not quite sure how to set these options in the benchmarks...

Ah okay then we probably won't see any changes since these need to be enabled for the changes here to take effect. Posting a comparison I did locally:

Comparing main and feat_pushdown-hashes-hashjoinexec
--------------------
Benchmark tpch_sf1.json
--------------------
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query        ┃      main ┃ feat_pushdown-hashes-hashjoinexec ┃        Change ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 1     │  58.88 ms │                          57.03 ms │     no change │
│ QQuery 2     │  53.69 ms │                          30.18 ms │ +1.78x faster │
│ QQuery 3     │  66.45 ms │                          68.39 ms │     no change │
│ QQuery 4     │  41.55 ms │                          41.23 ms │     no change │
│ QQuery 5     │ 108.33 ms │                          68.41 ms │ +1.58x faster │
│ QQuery 6     │  28.36 ms │                          26.23 ms │ +1.08x faster │
│ QQuery 7     │ 101.16 ms │                          56.93 ms │ +1.78x faster │
│ QQuery 8     │ 111.82 ms │                          78.32 ms │ +1.43x faster │
│ QQuery 9     │ 126.30 ms │                         127.26 ms │     no change │
│ QQuery 10    │  94.72 ms │                          64.64 ms │ +1.47x faster │
│ QQuery 11    │  36.03 ms │                          17.83 ms │ +2.02x faster │
│ QQuery 12    │  69.64 ms │                          58.65 ms │ +1.19x faster │
│ QQuery 13    │  34.31 ms │                          33.93 ms │     no change │
│ QQuery 14    │  43.37 ms │                          41.74 ms │     no change │
│ QQuery 15    │  49.23 ms │                          48.76 ms │     no change │
│ QQuery 16    │  35.28 ms │                          30.01 ms │ +1.18x faster │
│ QQuery 17    │ 125.91 ms │                         112.71 ms │ +1.12x faster │
│ QQuery 18    │ 160.70 ms │                         203.86 ms │  1.27x slower │
│ QQuery 19    │  81.69 ms │                          68.15 ms │ +1.20x faster │
│ QQuery 20    │  47.11 ms │                          47.74 ms │     no change │
│ QQuery 21    │ 149.61 ms │                         113.31 ms │ +1.32x faster │
│ QQuery 22    │  18.61 ms │                          17.81 ms │     no change │
└──────────────┴───────────┴───────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Benchmark Summary                                ┃           ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ Total Time (main)                                │ 1642.74ms │
│ Total Time (feat_pushdown-hashes-hashjoinexec)   │ 1413.10ms │
│ Average Time (main)                              │   74.67ms │
│ Average Time (feat_pushdown-hashes-hashjoinexec) │   64.23ms │
│ Queries Faster                                   │        12 │
│ Queries Slower                                   │         1 │
│ Queries with No Change                           │         9 │
│ Queries with Failure                             │         0 │
└──────────────────────────────────────────────────┴───────────┘

@alamb
Copy link
Contributor

alamb commented Sep 17, 2025

🤖: Benchmark completed

Details

Comparing HEAD and feat_pushdown-hashes-hashjoinexec
--------------------
Benchmark clickbench_extended.json
--------------------
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Query        ┃        HEAD ┃ feat_pushdown-hashes-hashjoinexec ┃    Change ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ QQuery 0     │  2717.61 ms │                        2725.63 ms │ no change │
│ QQuery 1     │  1351.49 ms │                        1383.95 ms │ no change │
│ QQuery 2     │  2518.22 ms │                        2567.39 ms │ no change │
│ QQuery 3     │  1174.45 ms │                        1172.97 ms │ no change │
│ QQuery 4     │  2266.99 ms │                        2238.41 ms │ no change │
│ QQuery 5     │ 27509.19 ms │                       27546.37 ms │ no change │
│ QQuery 6     │  4211.49 ms │                        4245.39 ms │ no change │
│ QQuery 7     │  3546.52 ms │                        3562.03 ms │ no change │
└──────────────┴─────────────┴───────────────────────────────────┴───────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                                ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                                │ 45295.95ms │
│ Total Time (feat_pushdown-hashes-hashjoinexec)   │ 45442.14ms │
│ Average Time (HEAD)                              │  5661.99ms │
│ Average Time (feat_pushdown-hashes-hashjoinexec) │  5680.27ms │
│ Queries Faster                                   │          0 │
│ Queries Slower                                   │          0 │
│ Queries with No Change                           │          8 │
│ Queries with Failure                             │          0 │
└──────────────────────────────────────────────────┴────────────┘
--------------------
Benchmark clickbench_partitioned.json
--------------------
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query        ┃        HEAD ┃ feat_pushdown-hashes-hashjoinexec ┃        Change ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 0     │     2.15 ms │                           2.22 ms │     no change │
│ QQuery 1     │    50.36 ms │                          49.92 ms │     no change │
│ QQuery 2     │   137.12 ms │                         140.45 ms │     no change │
│ QQuery 3     │   163.55 ms │                         163.97 ms │     no change │
│ QQuery 4     │  1042.87 ms │                        1079.35 ms │     no change │
│ QQuery 5     │  1503.48 ms │                        1629.49 ms │  1.08x slower │
│ QQuery 6     │     2.20 ms │                           2.17 ms │     no change │
│ QQuery 7     │    55.16 ms │                          55.88 ms │     no change │
│ QQuery 8     │  1450.70 ms │                        1483.81 ms │     no change │
│ QQuery 9     │  1758.13 ms │                        1899.19 ms │  1.08x slower │
│ QQuery 10    │   375.94 ms │                         380.50 ms │     no change │
│ QQuery 11    │   436.65 ms │                         439.74 ms │     no change │
│ QQuery 12    │  1370.17 ms │                        1395.11 ms │     no change │
│ QQuery 13    │  2128.89 ms │                        2168.22 ms │     no change │
│ QQuery 14    │  1264.19 ms │                        1302.04 ms │     no change │
│ QQuery 15    │  1185.43 ms │                        1262.46 ms │  1.06x slower │
│ QQuery 16    │  2628.93 ms │                        2698.18 ms │     no change │
│ QQuery 17    │  2646.98 ms │                        2684.21 ms │     no change │
│ QQuery 18    │  5350.80 ms │                        5020.88 ms │ +1.07x faster │
│ QQuery 19    │   128.21 ms │                         127.70 ms │     no change │
│ QQuery 20    │  2051.17 ms │                        2077.75 ms │     no change │
│ QQuery 21    │  2382.70 ms │                        2369.91 ms │     no change │
│ QQuery 22    │  4069.62 ms │                        4029.18 ms │     no change │
│ QQuery 23    │ 15388.80 ms │                       12911.70 ms │ +1.19x faster │
│ QQuery 24    │   224.76 ms │                         228.39 ms │     no change │
│ QQuery 25    │   510.24 ms │                         509.16 ms │     no change │
│ QQuery 26    │   216.79 ms │                         225.03 ms │     no change │
│ QQuery 27    │  2983.96 ms │                        2906.25 ms │     no change │
│ QQuery 28    │ 23267.75 ms │                       23351.25 ms │     no change │
│ QQuery 29    │   963.44 ms │                        1019.77 ms │  1.06x slower │
│ QQuery 30    │  1349.04 ms │                        1326.20 ms │     no change │
│ QQuery 31    │  1350.83 ms │                        1335.29 ms │     no change │
│ QQuery 32    │  4846.62 ms │                        4877.66 ms │     no change │
│ QQuery 33    │  5932.21 ms │                        5797.16 ms │     no change │
│ QQuery 34    │  6005.87 ms │                        6076.10 ms │     no change │
│ QQuery 35    │  2078.60 ms │                        2080.23 ms │     no change │
│ QQuery 36    │   124.39 ms │                         122.41 ms │     no change │
│ QQuery 37    │    55.88 ms │                          54.30 ms │     no change │
│ QQuery 38    │   125.99 ms │                         126.27 ms │     no change │
│ QQuery 39    │   208.15 ms │                         202.62 ms │     no change │
│ QQuery 40    │    44.99 ms │                          43.80 ms │     no change │
│ QQuery 41    │    42.19 ms │                          42.26 ms │     no change │
│ QQuery 42    │    33.63 ms │                          33.99 ms │     no change │
└──────────────┴─────────────┴───────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                                ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                                │ 97939.49ms │
│ Total Time (feat_pushdown-hashes-hashjoinexec)   │ 95732.17ms │
│ Average Time (HEAD)                              │  2277.66ms │
│ Average Time (feat_pushdown-hashes-hashjoinexec) │  2226.33ms │
│ Queries Faster                                   │          2 │
│ Queries Slower                                   │          4 │
│ Queries with No Change                           │         37 │
│ Queries with Failure                             │          0 │
└──────────────────────────────────────────────────┴────────────┘
--------------------
Benchmark tpch_mem_sf1.json
--------------------
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query        ┃      HEAD ┃ feat_pushdown-hashes-hashjoinexec ┃        Change ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 1     │ 170.84 ms │                         168.69 ms │     no change │
│ QQuery 2     │  27.69 ms │                          27.60 ms │     no change │
│ QQuery 3     │  45.32 ms │                          46.66 ms │     no change │
│ QQuery 4     │  27.50 ms │                          27.10 ms │     no change │
│ QQuery 5     │  75.04 ms │                          77.54 ms │     no change │
│ QQuery 6     │  19.38 ms │                          19.93 ms │     no change │
│ QQuery 7     │ 148.69 ms │                         148.04 ms │     no change │
│ QQuery 8     │  38.63 ms │                          32.15 ms │ +1.20x faster │
│ QQuery 9     │ 103.45 ms │                          86.18 ms │ +1.20x faster │
│ QQuery 10    │  59.85 ms │                          59.21 ms │     no change │
│ QQuery 11    │  41.71 ms │                          40.99 ms │     no change │
│ QQuery 12    │  51.25 ms │                          50.80 ms │     no change │
│ QQuery 13    │  47.90 ms │                          47.13 ms │     no change │
│ QQuery 14    │  14.05 ms │                          14.06 ms │     no change │
│ QQuery 15    │  24.19 ms │                          24.27 ms │     no change │
│ QQuery 16    │  24.75 ms │                          23.96 ms │     no change │
│ QQuery 17    │ 146.04 ms │                         147.61 ms │     no change │
│ QQuery 18    │ 331.51 ms │                         330.26 ms │     no change │
│ QQuery 19    │  36.24 ms │                          36.63 ms │     no change │
│ QQuery 20    │  48.12 ms │                          48.99 ms │     no change │
│ QQuery 21    │ 218.30 ms │                         228.72 ms │     no change │
│ QQuery 22    │  19.70 ms │                          19.98 ms │     no change │
└──────────────┴───────────┴───────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Benchmark Summary                                ┃           ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ Total Time (HEAD)                                │ 1720.15ms │
│ Total Time (feat_pushdown-hashes-hashjoinexec)   │ 1706.50ms │
│ Average Time (HEAD)                              │   78.19ms │
│ Average Time (feat_pushdown-hashes-hashjoinexec) │   77.57ms │
│ Queries Faster                                   │         2 │
│ Queries Slower                                   │         0 │
│ Queries with No Change                           │        20 │
│ Queries with Failure                             │         0 │
└──────────────────────────────────────────────────┴───────────┘

@adriangb
Copy link
Contributor

adriangb commented Oct 8, 2025

@rkrishn7 sorry if I haven't looped back here. I went on a bit of a tangent exploring #17632 and then had some vacation and a team offsite. This is overall very exciting work that I think will help a lot of people.

My main concern with this change is the overhead and making a CPU / memory tradeoff decision for users. I think we might be able to ship it as an experimental thing with the feature flag defaulting to false as you've done in this PR but long term I worry that an extra 8GB or RAM consumed might be too much. Do you have any numbers on how fast and how much RAM these 3 different scenarios use for some queries? I don't mean to ask you to run them all but I do remember you mentioning you have already.

  1. No hashes pushdown.
  2. Build a single hash table (this PR).
  3. Push down the existing hash tables w/ a CASE statement for which hash table to check based on the same partitioning as RepartitionExec.

My hypothesis is that the table will look something like this:

(1) (2) (3)
Runtime 300s 25s 30s
Peak mem 8GB 16GB 8GB

If that were the case, which is just a guess at this point, making a query 10x faster with no extra memory use is easy to justify, everyone wants that! Choosing to make some queries 17% faster for 100% more memory use is harder to justify. If the performance difference is larger and we think it is justified in some cases maybe we can at least try to reserve the extra memory and fall back to re-using the existing hash tables?

I also think it's worth thinking about integrating your suggestion from our conversation to use an IN LIST expression because it's even integrated into bloom filter pruning and predicate pruning. I see basically no reason to not do that for small build side result sets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
common Related to common crate documentation Improvements or additions to documentation execution Related to the execution crate 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.

Push down entire hash table from HashJoinExec into scans
4 participants