Uh oh!
There was an error while loading. Please reload this page.
[SPARK-35350][SQL] Add code-gen for left semi sort merge join - #32528
[SPARK-35350][SQL] Add code-gen for left semi sort merge join#32528c21 wants to merge 3 commits into
Conversation
c21
commented
May 12, 2021
cc @cloud-fan and @maropu could you help take a look when you have time? Thanks. |
SparkQA
commented
May 13, 2021
Kubernetes integration test starting |
SparkQA
commented
May 13, 2021
Kubernetes integration test status failure |
| """.stripMargin | ||
| } | ||
| lazy val semiJoin = { |
There was a problem hiding this comment.
How about extracting this block as a private method like codegenXXXX just like HashJoin?
There was a problem hiding this comment.
@maropu - yes I was thinking at the first place but worried about number of parameters to be too many. Refined the code a bit and updated now.
| case _ => false | ||
| } | ||
| val inMemoryThreshold = | ||
| if (onlyBufferFirstMatchedRow) { |
There was a problem hiding this comment.
How about moving this branch into the getInMemoryThreshold side?
// Flag to only buffer first matched row, to avoid buffering unnecessary rows.
private lazy val onlyBufferFirstMatchedRow = (joinType, condition) match {
case (LeftSemi, None) => true
case _ => false
}
private def getInMemoryThreshold: Int = {
if (onlyBufferFirstMatchedRow) {
1
} else {
sqlContext.conf.sortMergeJoinExecBufferInMemoryThreshold
}
}
There was a problem hiding this comment.
+1, lazy val can probably be def as the logic is super simple
There was a problem hiding this comment.
Good call. Actually the non-code-gen path can also depend on this, so I make it just a val now.
SparkQA
commented
May 13, 2021
Test build #138476 has finished for PR 32528 at commit
|
c21
commented
May 13, 2021
To ease for review, the change for all plan files is used by followed command: None of them are updated manually. |
| case _: InnerLike => innerJoin | ||
| case LeftOuter | RightOuter => outerJoin | ||
| case _: InnerLike => | ||
| codegenInner(findNextJoinRows, beforeLoop, iterator, bufferedRow, condCheck, outputRow, |
There was a problem hiding this comment.
shall we pass beforeLoop.trim so that we don't need to do it in all the 3 methods?
There was a problem hiding this comment.
Actually after double checking, we do not need to do beforeLoop.trim as beforeLoop already has stripMargin, and has no trailing spaces. Also updated to avoid repeated conditionCheck.trim
| s""" | ||
| |while ($findNextJoinRows) { | ||
| | ${beforeLoop.trim} | ||
| | boolean $hasOutputRow = false; |
There was a problem hiding this comment.
do we need this flag if we are sure matchIterator has at most one element?
There was a problem hiding this comment.
@cloud-fan - matchIterator will only has at most one element if join condition is empty. So yes we don't need this if join condition is empty. But consider the extra code is just a while loop check on hasOutputRow, and set value of hasOutputRow, I don't see much value to specialize another code-gen for left semi join without join condition. WDYT?
SparkQA
commented
May 13, 2021
Kubernetes integration test starting |
SparkQA
commented
May 13, 2021
Kubernetes integration test status failure |
SparkQA
commented
May 13, 2021
Kubernetes integration test starting |
SparkQA
commented
May 13, 2021
Kubernetes integration test status failure |
SparkQA
commented
May 13, 2021
Test build #138500 has finished for PR 32528 at commit
|
cloud-fan
commented
May 13, 2021
thanks, merging to master! |
SparkQA
commented
May 13, 2021
Test build #138506 has finished for PR 32528 at commit
|
c21
commented
May 13, 2021
Thank you @cloud-fan and @maropu for review! |
What changes were proposed in this pull request?
As title. This PR is to add code-gen support for LEFT SEMI sort merge join. The main change is to add
semiJoincode path inSortMergeJoinExec.doProduce()and introduceonlyBufferFirstMatchedRowinSortMergeJoinExec.genScanner(). The latter is for left semi sort merge join without condition. For this kind of query, we don't need to buffer all matched rows, but only the first one (this is same as non-code-gen code path).Example query:
Example of generated code for the query:
Why are the changes needed?
Improve query CPU performance. Test with one query:
Seeing 30% of run-time improvement:
Does this PR introduce any user-facing change?
No.
How was this patch tested?
Added unit test in
WholeStageCodegenSuite.scalaandExistenceJoinSuite.scala.