概述
逻辑计划转换为物理计划
SQL被解析为逻辑计划后,会被交给SessionState的executePlan方法,转换为QueryExecution:
def executePlan(plan: LogicalPlan): QueryExecution = createQueryExecution(plan)
QueryExecution的构造过程将LogicalPlan转换为物理计划:
protected def planner = sparkSession.sessionState.planner
// 1
lazy val analyzed: LogicalPlan = {
SparkSession.setActiveSession(sparkSession)
sparkSession.sessionState.analyzer.executeAndCheck(logical)
}
// 2
lazy val optimizedPlan: LogicalPlan = sparkSession.sessionState.optimizer.execute(withCachedData)
// 3
lazy val sparkPlan: SparkPlan = {
SparkSession.setActiveSession(sparkSession)
planner.plan(ReturnAnswer(optimizedPlan)).next()
}
// 4
// executedPlan should not be used to initialize any SparkPlan. It should be
// only used for execution.
lazy val executedPlan: SparkPlan = prepareForExecution(sparkPlan)
/** Internal version of the RDD. Avoids copies and has no schema */
lazy val toRdd: RDD[InternalRow] = executedPlan.execute()
第3步中SparkPlanner将逻辑计划转换为物理计划。
JoinSelection是SparkPlanner的一条策略,用于将逻辑计划中的Join执行计划转换为合适的物理Join执行计划。
第4步中对物理计划进行进一步处理。其中包括在Join物理计划与其子物理计划之间插入Exchange物理计划(由EnsureRequirements规则实现),用于执行join前小表广播(BroadcastHashJoin)、shuffle并排序(SortMergeJoin)等使得数据分布满足join物理计划执行。
Join物理计划分类
join实现方式 | 物理计划 |
---|---|
BroadcastHashJoin | BroadcastHashJoinExec |
ShuffledHashJoin | ShuffledHashJoinExec |
SortMergeJoin | SortMergeJoinExec |
BroadcastNestedLoopJoin | BroadcastNestedLoopJoinExec |
CartesianProduct | CartesianProductExec |
选择策略
排除由hint显式指定的情况,通过表数据量、join类型、是否存在等值join条件等策略选择物理Join实现。
join类型如下
- InnerLike
- Inner
- Cross
<