-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-13136][SQL] Create a dedicated Broadcast exchange operator #11083
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
Changes from 19 commits
aa7120e
c2b7533
6a5568a
9adecdd
d0194fb
02a61b8
c12c8e6
c7dd7ae
e847383
d73f11c
9c0f4bf
da4a966
681f347
7db240a
3ad839d
1116768
a5501cf
c7429bb
b12bbc2
9d52650
54b558d
f33d2cb
28363c8
f812a31
4b5978b
c8c175e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,7 @@ | |
|
|
||
| package org.apache.spark.sql.catalyst.plans.physical | ||
|
|
||
| import org.apache.spark.sql.catalyst.InternalRow | ||
| import org.apache.spark.sql.catalyst.expressions._ | ||
| import org.apache.spark.sql.types.{DataType, IntegerType} | ||
|
|
||
|
|
@@ -75,6 +76,27 @@ case class OrderedDistribution(ordering: Seq[SortOrder]) extends Distribution { | |
| def clustering: Set[Expression] = ordering.map(_.child).toSet | ||
| } | ||
|
|
||
| /** | ||
| * Marker trait to identify the shape in which tuples are broadcasted. Typical examples of this are | ||
| * identity (tuples remain unchanged) or hashed (tuples are converted into some hash index). | ||
| */ | ||
| trait BroadcastMode { | ||
| def transform(rows: Array[InternalRow]): Any | ||
| } | ||
|
|
||
| /** | ||
| * IdentityBroadcastMode requires that rows are broadcasted in their original form. | ||
| */ | ||
| case object IdentityBroadcastMode extends BroadcastMode { | ||
| override def transform(rows: Array[InternalRow]): Array[InternalRow] = rows | ||
| } | ||
|
|
||
| /** | ||
| * Represents data where tuples are broadcasted to every node. It is quite common that the | ||
| * entire set of tuples is transformed into different data structure. | ||
| */ | ||
| case class BroadcastDistribution(mode: BroadcastMode) extends Distribution | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok for now, but technically once we introduce this, "Distribution" is not just about "distribution" anymore, but rather some data property. |
||
|
|
||
| /** | ||
| * Describes how an operator's output is split across partitions. The `compatibleWith`, | ||
| * `guarantees`, and `satisfies` methods describe relationships between child partitionings, | ||
|
|
@@ -213,7 +235,10 @@ case class RoundRobinPartitioning(numPartitions: Int) extends Partitioning { | |
| case object SinglePartition extends Partitioning { | ||
| val numPartitions = 1 | ||
|
|
||
| override def satisfies(required: Distribution): Boolean = true | ||
| override def satisfies(required: Distribution): Boolean = required match { | ||
| case _: BroadcastDistribution => false | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think this is ok for now, but technically we don't need to introduce an exchange if both sides of the join have only one partition. i guess this framework does not currently handle that. |
||
| case _ => true | ||
| } | ||
|
|
||
| override def compatibleWith(other: Partitioning): Boolean = other.numPartitions == 1 | ||
|
|
||
|
|
@@ -351,3 +376,21 @@ case class PartitioningCollection(partitionings: Seq[Partitioning]) | |
| partitionings.map(_.toString).mkString("(", " or ", ")") | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Represents a partitioning where rows are collected, transformed and broadcasted to each | ||
| * node in the cluster. | ||
| */ | ||
| case class BroadcastPartitioning(mode: BroadcastMode) extends Partitioning { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and partitioning here isn't really just about partitioning anymore. it also includes how data is physically organized on each partition. |
||
| override val numPartitions: Int = 1 | ||
|
|
||
| override def satisfies(required: Distribution): Boolean = required match { | ||
| case BroadcastDistribution(m) if m == mode => true | ||
| case _ => false | ||
| } | ||
|
|
||
| override def compatibleWith(other: Partitioning): Boolean = other match { | ||
| case BroadcastPartitioning(m) if m == mode => true | ||
| case _ => false | ||
| } | ||
| } | ||
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'd move this and IdentityBroadcastMode into a new file.