11,spark源码分析-Catalyst流程解析(4)

此阶段是从优化过的LogicalPlan转换成物理执行计划PhysicalPlan
在这里插入图片描述
plan 是从BaseSessionStateBuilder中实例化的。
在这里插入图片描述
sparkPlan的继承关系:
sparkPlan -> SparkStrategies -> QueryPlanner -> TreeNode

sparkPlan继承了SparkStrategies, strategies()方法里面包含四部分,
1:自定义实验的策略
2:sparkplan扩展的一些策略。
4: 一些基础操作的策略BasicOperators.
3:sparkplan 基于hiveStrategies的扩展。

在这里插入图片描述
一下是基于hive的扩展策略,也是一般场景中使用比较多的。
在这里插入图片描述

这个地方说明一个比较重要的概念,PlanLater, 字面意思就是这个地方不做处理,以后在搞。其实个人觉得没有什么有意义。
在这里插入图片描述

在plan()方法中,最终要的就是拿到strategies进行迭代,把当前的LogicalPlan构造成新的PhysicalPlan的过程。然后把父亲节点是PlanLater的,替换成子节点。
在这里插入图片描述

FileSourceStrategy

一个针对Hadoop文件系统做的策略,当执行计划的底层Relation是HadoopFsRelation时会调用到,用来扫描文件。
在spark2.3的场景中,如果是orc文件,并且开启了矢量化读取。就会将hiveTableRelation转换成HadoopFsRelation. 最终生成FlleSourceScanExec, 并且filter可以下推到数据源执行。使用文件读。在效率上有一定的提升。

比如:algo_mix_search_codes是一个orc-file的hive表,在生成物理执行计划的时候,因为使用了矢量化读取,使用了FileSourceStrategy的策略进行读取,并且把一些字段进行了下推查询。

在这里插入图片描述

FileSourceScanExec

FileSourceScanExec把读取的文件进行了切分,最终生成了FileScanRDD, FileSourceScanExec决定了读取文件的最大并发度
里面包含了对分桶表和非分桶表的并发读取做了相关设置。我们主要看非分桶表:
以下是最主要的计算逻辑:

Math.min(defaultMaxSplitBytes, Math.max(openCostInBytes, (totalByte + n * openCostInBytes) / defaultParallelism))

首先决定maxSplitBytes 的因素有

  • spark.sql.files.maxPartitionBytes() 最主要调节并发度的数据, 每个分区最大的数据量。
  • spark.sql.files.openCostInBytes 读取一个文件的时间能够读多少数据(在小文件的场景下可以基于它来调整并发)。
  • spark.default.parallelism 默认并发数,2 ,spark.default.parallelism 如果没有设置的话,取 CoarseGrainedSchedulerBackend 的 conf.getInt(“spark.default.parallelism”, math.max(totalCoreCount.get(), 2))。一般而言读取hive表都是在最初的时间节点,所以默认spark.default.parallelism = 2;

https://blog.csdn.net/xianzhen376/article/details/101625408
这篇文章对这个做了详细的说明,在这我就不多说了,我主要说一下在不同场景下用哪个配置比较好使:

  • totalBytes比较大, 这种场景其实可以忽略掉openCostInBytes(非极端场景)。决定因素在于spark.sql.files.maxPartitionBytes
  • totalBytes比较小 < defaultMaxSplitBytes, 文件数比较多,这个时候就不能忽略掉openCostInBytes. 否者会导致并发数很小,这个时候可以减小openCostInBytes来保证并发数,或者通过手工控制defaultParallelism。

在这里插入图片描述

注:需要说明的一点,在这个场景下使用spark.hadoop.mapreduce.input.fileinputformat.split.maxsize配置是不生效的。

HiveTableScans

对于所有hiveTableRelation关系的表,直接走HiveTableScanExec(); 比如非矢量化读取场景,hive表的查询都会走这个,在矢量化读的场景下,非Orc, Parquet文件的也要走这个。

在这里插入图片描述

比如:acm_etl_cart 是一个rc-file的hive表。在生成物理执行计划的时候,最终使用HiveTableScan的策略进行读取。它的ser= org.apache.hadoop.hive.serde2.columnar.LazyBinaryColumnarSerDe
在这里插入图片描述

注:下推查询必须对表事先进行分析使用才有效。

这个地方说一下读取文件并发度的问题,因为这边使用了不同的ser,所以应该根据hadoop的FileInputFormat来决定。
以rc-file为例,因为rc-file是可以切分的,所以可以使用下面的配置项来修改并发度,如果没有配置下列配置项,并发度就是文件数。如果文件不可切分,文件数就是最大并发数。

  • set spark.hadoop.mapreduce.input.fileinputformat.split.maxsize=67108864;

  • set spark.hadoop.mapreduce.input.fileinputformat.split.minsize.per.node=67108864;

  • set spark.hadoop.mapreduce.input.fileinputformat.split.minsize.per.rack=67108864;

DataSourceStrategy

开发者可以自定义自己的DataSource。

Aggregation

顾名思义,执行聚合函数的策略。
分为聚合不包括distinct和包括distinct两种,这个后续再仔细说。

InMemoryScans

当数据在内存中被缓存过,就会用到该策略。具体的执行是InMemoryTableScanExec。

JoinSelection

包括了不同join的exec执行逻辑。

  • broadcast-hint
  • boardcast
  • shuffleHashJoin
  • sortMergeJoin

在这里插入图片描述
关于join如何判断驱动表和非驱动表。很大程度是根据表的大小的。表大小的获取是从LogincalPlanStats获取的。
在这里插入图片描述
每个算子都有自己的预估方法
CBO打开/关闭,有些算子的预估方法不一样,如AggregateEstimation/FilterEstimation/JoinEstimation/ProjectEstimation,其它算子CBO打开/关闭使用一套预估方法。
在这里插入图片描述

  • 如果有hint语法,使用BroadcastHashJoinExec
  • 如果表totalSize < spark.sql.autoBroadcastJoinThreshold 使用BroadcastHashJoinExec。
  • shuffledHashJoin 这个就不讲了,因为不怎么用
  • 如果左表是可排序的, spark.sql.join.preferSortMergeJoin = true, 使用SortMergeJoinExec

BasicOperators

一些基本操作的执行策略,如flatMap,sort,project等,但是实际上大都是给这些节点的子节点套上一个PlanLater

参考

https://blog.csdn.net/orisonchan/article/details/83045152
https://blog.csdn.net/xianzhen376/article/details/101625408

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值