在SparkPlan中插入Shuffle的操作,如果前后2个SparkPlan的outputPartitioning不一样的话,则中间需要插入Shuffle的动作,比分说聚合函数,先局部聚合,然后全局聚合,局部聚合和全局聚合的分区规则是不一样的,中间需要进行一次Shuffle。
比方说sql语句:selectSUM(id) from test group by dev_chnid
其从逻辑计划转换为的物理计划如下:
Aggregate false, [dev_chnid#0], [CombineSum(PartialSum#45L) AS c0#43L]
Aggregate true, [dev_chnid#0], [dev_chnid#0,SUM(id#17L) AS PartialSum#45L]
PhysicalRDD [dev_chnid#0,id#17L], MapPartitionsRDD[1]
其中Aggregate的第一个构造函数指明了其ChildDistribution,即规定了该SparkPlan的分区规则
case class Aggregate(
partial: Boolean,
groupingExpressions: Seq[Expression],
aggregateExpressions: Seq[NamedExpression],
child: SparkPlan)
extends UnaryNode {
override def requiredChildDistribution: List[Distribution] = {
if (partial) {
UnspecifiedDistribution :: Nil //当为true时,则对于Child的分区规则无所谓
} else {
if (groupingExpressions == Nil) {
AllTuples :: Nil
} else {
ClusteredDistribution(groupingExpressions) :: Nil //当为false时,必须按照聚合字段进行分区,此时为dev_chnid
}
}
}
……
}
因此如果按照以上SparkPlan执行的话,其流程图如下: