自适应查询执行
自适应查询执行(AQE)是在查询执行期间发生的查询重新优化。
运行时重新优化的动机是Databricks在shuffle和广播交换(在AQE中称为查询阶段)结束时具有最新的准确统计信息。因此,Databricks可以选择更好的物理策略,选择最优的shuffle后分区大小和数量,或者进行以前需要提示的优化,例如倾斜连接处理。
这在统计信息收集未打开或统计信息过时时非常有用。它在静态派生统计信息不准确的地方也很有用,比如在复杂查询的中间,或者在发生数据倾斜之后。
功能
在Databricks Runtime 7.3 LTS及以上版本中,AQE默认开启。它有4个主要特点:
动态地将排序合并连接更改为广播散列连接。
在shuffle交换后动态合并分区(将小分区合并为合理大小的分区)。非常小的任务具有较差的I/O吞吐量,并且往往会受到调度开销和任务设置开销的影响。组合小任务可以节省资源并提高集群吞吐量。
动态处理排序合并连接和洗牌散列连接中的倾斜,通过将倾斜的任务拆分(并在需要时复制)为大致均匀大小的任务。
动态检测并传播空关系。
应用程序
AQE适用于以下所有查询:
的非
至少包含一个交换(通常在有连接、聚合或窗口时)、一个子查询或两者都包含。
并非所有应用aqi的查询都必须重新优化。重新优化可能会产生与静态编译的查询计划不同的查询计划,也可能不会。要确定查询的计划是否已被AQE更改,请参阅以下部分,查询计划.
查询计划
本节讨论如何以不同的方式检查查询计划。
火花UI
DataFrame.explain ()
有效性
如果一个或多个AQE优化生效,查询计划将发生变化。这些AQE优化的效果可以通过当前和最终计划与当前和最终计划中的初始计划和特定计划节点之间的差异来证明。
动态更改排序合并连接为广播散列连接:当前/最终计划与初始计划之间的不同物理连接节点
动态合并分区:节点
CustomShuffleReader
有财产合并
动态处理倾斜连接:节点
SortMergeJoin
与字段isSkew
是真实的。动态检测和传播空关系:将部分(或整个)计划替换为节点LocalTableScan,其中关系字段为空。
配置
启用和禁用自适应查询执行
财产 |
---|
spark.databricks.optimizer.adaptive.enabled 类型: 是否启用或禁用自适应查询执行。 默认值: |
动态更改排序合并连接为广播散列连接
财产 |
---|
spark.databricks.adaptive.autoBroadcastJoinThreshold 类型: 在运行时触发切换到广播连接的阈值。 默认值: |
动态合并分区
财产 |
---|
spark.sql.adaptive.coalescePartitions.enabled 类型: 是否启用或禁用分区合并。 默认值: |
spark.sql.adaptive.advisoryPartitionSizeInBytes 类型: 合并后的目标尺寸。合并后的分区大小将接近但不大于此目标大小。 默认值: |
spark.sql.adaptive.coalescePartitions.minPartitionSize 类型: 合并后分区的最小大小。合并的分区大小将不小于此大小。 默认值: |
spark.sql.adaptive.coalescePartitions.minPartitionNum 类型: 合并后的最小分区数。不推荐,因为设置显式地覆盖 默认值:2x否。簇核 |
动态处理倾斜连接
财产 |
---|
spark.sql.adaptive.skewJoin.enabled 类型: 是否启用或禁用倾斜连接处理。 默认值: |
spark.sql.adaptive.skewJoin.skewedPartitionFactor 类型: 当与分区大小的中位数相乘时,该因子有助于确定分区是否倾斜。 默认值: |
spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes 类型: 用于确定分区是否倾斜的阈值。 默认值: |
当两者都有时,分区被认为是倾斜的(分区大小>skewedPartitionFactor*中位数分区大小)
而且(分区大小>skewedPartitionThresholdInBytes)
是真正的
.
动态检测和传播空关系
财产 |
---|
spark.databricks.adaptive.emptyRelationPropagation.enabled 类型: 是否启用或禁用动态空关系传播。 默认值: |
常见问题(FAQ)
本节:
为什么在已经启用分区合并的情况下,AQE没有更改shuffle分区号?
AQE不会改变初始分区号。建议您为shuffle分区号设置一个合理的高值,并让AQE在查询的每个阶段根据输出数据大小合并小分区。
如果你在工作中看到溢出,你可以试试:
增加shuffle分区编号配置:
spark.sql.shuffle.partitions
通过设置使自动优化shuffle
spark.databricks.adaptive.autoOptimizeShuffle.enabled
来真正的
为什么AQE没有广播一个小的连接表?
如果期望被广播的关系的大小确实低于这个阈值,但仍然没有被广播:
检查连接类型。某些连接类型不支持广播,例如,a的左关系
左外加入
不能广播。也可能是该关系包含大量空分区,在这种情况下,大多数任务可以通过排序合并连接快速完成,或者可以通过倾斜连接处理进行优化。如果非空分区的百分比低于
spark.sql.adaptive.nonEmptyPartitionRatioForBroadcastJoin
.
我还应该在启用AQE时使用广播连接策略提示吗?
是的。静态计划的广播连接通常比由AQE动态计划的广播连接性能更好,因为AQE可能直到对连接的两端执行shuffle之后才切换到广播连接(此时已获得实际关系大小)。因此,如果您非常了解您的查询,使用广播提示仍然是一个不错的选择。AQE将以与静态优化相同的方式尊重查询提示,但仍然可以应用不受提示影响的动态优化。
倾斜连接提示和AQE倾斜连接优化之间的区别是什么?我应该用哪一个?
建议依赖于AQE倾斜连接处理,而不是使用倾斜连接提示,因为AQE倾斜连接是完全自动的,通常比提示对应的性能更好。
为什么AQE没有自动调整我的连接顺序?
在Databricks Runtime 7.3 LTS中,动态连接重新排序不是aqe3的一部分。
为什么AQE没有检测到我的数据倾斜?
为了将分区检测为倾斜分区,必须满足两个大小条件:
分区大小大于
spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes
(默认256 mb)分区大小大于所有分区的中位数大小乘以倾斜分区因子
spark.sql.adaptive.skewJoin.skewedPartitionFactor
(默认5)
此外,对某些连接类型的倾斜处理支持是有限的,例如左外加入
,只有左侧偏置才能优化。