AQE简介
从spark configuration,到在最早在spark 1.6版本就已经有了AQE;到了spark 2.x版本,intel大数据团队进行了相应的原型开发和实践;到了spark 3.0时代,Databricks和intel一起为社区贡献了新的AQE
spark 3.0.1中的AQE的配置
| 配置项 | 默认值 | 官方说明 | 分析 |
|---|---|---|---|
| spark.sql.adaptive.enabled | false | 是否开启自适应查询 | 此处设置为true开启 |
| spark.sql.adaptive.coalescePartitions.enabled | true | 是否合并临近的shuffle分区(根据’spark.sql.adaptive.advisoryPartitionSizeInBytes’的阈值来合并) | 此处默认为true开启,分析见: 分析1 |
| spark.sql.adaptive.coalescePartitions.initialPartitionNum | (none) | shuffle合并分区之前的初始分区数,默认为spark.sql.shuffle.partitions的值 | 分析见:分析2 |
| spark.sql.adaptive.coalescePartitions.minPartitionNum | (none) | shuffle 分区合并后的最小分区数,默认为spark集群的默认并行度 | 分析见: 分析3 |
| spark.sql.adaptive.advisoryPartitionSizeInBytes | 64MB | 建议的shuffle分区的大小,在合并分区和处理join数据倾斜的时候用到 | 分析见:分析3 |
| spark.sql.adaptive.skewJoin.enabled | true | 是否开启join中数据倾斜的自适应处理 | |
| spark.sql.adaptive.skewJoin.skewedPartitionFactor | 5 | 数据倾斜判断因子,必须同时满足skewedPartitionFactor和skewedPartitionThresholdInBytes | 分析见:分析4 |
| spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes | 256MB | 数据倾斜判断阈值,必须同时满足skewedPartitionFactor和skewedPartitionThresholdInBytes | 分析见:分析4 |
| spark.sql.adaptive.logLevel | debug | 配置自适应执行的计划改变日志 | 调整为info级别,便于观察自适应计划的改变 |
| spark.sql.adaptive.nonEmptyPartitionRatioForBroadcastJoin | 0.2 | 转为broadcastJoin的非空分区比例阈值,>=该值,将不会转换为broadcastjoin | 分析见:分析5 |
分析1
在OptimizeSkewedJoin.scala中,我们看到ADVISORY_PARTITION_SIZE_IN_BYTES,也就是spark.sql.adaptive.advisoryPartitionSizeInBytes被引用的地方, (OptimizeSkewedJoin是物理计划中的规则)
/**
* The goal of skew join optimization is to make the data distribution more even. The target size
* to split skewed partitions is the average size of non-skewed partition, or the
* advisory partition size if avg size is smaller than it.
*/
private def targetSize(sizes: Seq[Long], medianSize: Long): Long = {
val advisorySize = conf.getConf(SQLConf.ADVISORY_PARTITION_SIZE_IN_BYTES)
val nonSkewSizes = sizes.filterNot(isSkewed(_, medianSize))
// It's impossible that all the partitions are skewed, as we use median size to define skew.
assert(nonSkewSizes.nonEmpty)
math.max(advisorySize, nonSkewSizes.sum / nonSkewSizes.length)
}
其中:
- nonSkewSizes为task非倾斜的分区
- targetSize返回的是max(非倾斜的分区的平均值,advisorySize),其中advisorySize为spark.sql.adaptive.advisoryPartitionSizeInBytes值,所以说
targetSize不一定是spark.sql.adaptive.advisoryPartitionSizeInBytes值 - medianSize值为task的分区大小的中位值
分析2
def numShufflePartitions: Int = {
if (adaptiveExecutionEnabled && coalesceShufflePartitionsEnabled) {
getConf(COALESCE_PARTITIONS_INITIAL_PARTITION_NUM).getOrElse(defaultNumShufflePartitions)
} else {
defaultNumShufflePartitions
}
}
从spark 3.0.1开始如果开启了AQE和shuffle分区合并,则用的是spark.sql.adaptive.coalescePartitions.initialPartitionNum,这在如果有多个shuffle stage的情况下,增加分区数,可以有效的增强shuffle分区合并的效果
分析3
在CoalesceShufflePartitions.scala,CoalesceShufflePartitions是一个物理计划的规则,会执行如下操作
if (!shuffleStages.forall(_.shuffle.canChangeNumPartitions)) {
plan

本文介绍了Spark中AQE的发展历程,重点分析了Spark 3.0.1中AQE的配置,包括分区合并、数据倾斜优化等方面的核心代码,如ShufflePartitionsUtil.coalescePartition和OptimizeSkewedJoin.optimizeSkewJoin,还说明了相关规则的调用位置及注意事项。
最低0.47元/天 解锁文章
2014

被折叠的 条评论
为什么被折叠?



