-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: modified JoinHashMap
build order for HashJoinStream
#8658
Conversation
JoinHashMap
build order for HashJoinStream
JoinHashMap
build order for HashJoinStream
Hi @korowa, this is a great extension. I suggest adding explanations in the code base, including docstrings for the mechanism and updating the docstring of the hash join. You can use https://textik.com, a great tool for drawing diagrams in docstring. I have another question regarding keeping the "head" inside the JoinHashMap next array. I've noticed that with each new row addition, the previous row indices need to be scanned, making the addition complexity linear instead of constant. Have you run performance benchmarks on low cardinality key columns to see how this affects performance? |
@metesynnada thank you! Regarding explanations -- I've added extended explanation of how build phase works in Regarding performance -- benchmark results are
(faster queries probably are no more than outliers)
Could you, please, recheck or point the LOC where scanning takes place? If I got it right -- the problem should be in
which should not produce linear complexity 🤔 (at least it definitely shouldn't perform worse than before) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @korowa -- this is a really nice refactor. I read it carefully and it looks very nice to me.
cc @Dandandan and @liukun4515 for your interest
@@ -156,8 +155,48 @@ impl JoinLeftData { | |||
/// | |||
/// Execution proceeds in 2 stages: | |||
/// | |||
/// 1. the **build phase** where a hash table is created from the tuples of the | |||
/// build side. | |||
/// 1. the **build phase** creates a hash table from the tuples of the build side, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you for this
@@ -1558,7 +1573,9 @@ mod tests { | |||
"| 3 | 5 | 9 | 20 | 5 | 80 |", | |||
"+----+----+----+----+----+----+", | |||
]; | |||
assert_batches_sorted_eq!(expected, &batches); | |||
|
|||
// Inner join output is expected to preserve both inputs order |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
"| 3 | 5 | 9 | 20 | 5 | 80 |", | ||
"| 2 | 5 | 8 | 20 | 5 | 80 |", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this also is neat to see it keep the same order as the input
@@ -151,6 +151,82 @@ pub trait JoinHashMapType { | |||
fn get_map(&self) -> &RawTable<(u64, u64)>; | |||
/// Returns a reference to the next. | |||
fn get_list(&self) -> &Self::NextType; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JoinHashMap
and this trait are getting big enough maybe to warrant moving to its own module (in a separate PR, perhaps)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe partial join output will add some more logic to JoinHashMap and make separate module reasonable (or even required) at that stage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I misunderstood an explanation in the related issue. This shouldn't degrade the performance, nicely done. However, are the JoinHashMap struct comments relevant after this change?
@metesynnada, yes, the PR is only related to the JoinHashMap input -- all its internals remains as they were before so all docs and comments for both JoinHashMap and moved pieces of code are still relevant. The only comment modification is related to missing |
Failed tests look like related to chrono-tz 0.8.5 + eggert/tz@1d0ae80 🤔 |
Pushed separate PR cause new chrono-tz release will affect test run on any branch. |
Which issue does this PR close?
Closes #8130.
Rationale for this change
The least harmful way of allowing
HashJoinStream
to process probe-side batch records in original order -- is to adjust build-side input to produce FIFO hash map as a result ofupdate_hash
, using current data structure without any modifications, and this can be achieved by reverse iteration over build-side input.What changes are included in this PR?
collect_left_input
iterates over collected batches in reverse orderupdate_hash
andbuild_equal_condition_join_indices
now acceptfifo_hashmap
argument, which determines the iteration order for input batches (SymmetricsHashJoin
execution has not changed)update_from_iter
&get_matched_indices
inJoinHashMapType
trait -- to unload join helper functions from HashMap-specific codeAre these changes tested?
assert_batches_sorted_eq
replaced withassert_batches_eq
for Inner / RightSemi / RightAnti non-partitioned join test cases to validate that join output preserves input(s) order.Are there any user-facing changes?
No.