使用倾斜提示进行倾斜联接优化

重要

本文档已停用,可能不会更新。 不再支持此内容中提到的产品、服务或技术。

不需要倾斜联接提示。 默认情况下,Databricks 使用自适应查询执行(AQE)处理倾斜。 请参阅 自适应查询执行

注意

spark.sql.adaptive.skewJoin.enabled 必须 True,这是 Azure Databricks 上的默认设置。

什么是数据倾斜?

数据倾斜是指 table的数据在群集中的分区之间分布不均匀的情况。 数据倾斜可能会严重降低查询性能,特别是对于那些带有连接的查询。 大表之间的联接需要混排数据,而倾斜可能导致群集中的工作极其不平衡。 如果查询似乎停滞在完成极少数任务(例如,200 个任务中的最后 3 个任务),则数据倾斜可能会影响查询。 若要验证数据倾斜是否影响查询,请执行以下操作:

  1. 单击停滞的阶段,验证它是否正在进行联接。
  2. 查询完成后,找到执行 join 操作并检查任务持续时间分布的阶段。
  3. 按工期从长到短对任务进行排序,并检查前几个任务。 如果一个任务完成时间比其他任务长得多,则存在偏差。

为了减轻倾斜,Azure Databricks 上的 Delta Lake SQL 会接受查询中的倾斜提示。 借助倾斜提示中的信息,Databricks Runtime 可以构建更好的查询计划,而该查询计划不会受到数据倾斜的影响。

使用关系名称配置倾斜提示

倾斜提示必须至少包含具有倾斜的关系的名称。 关系是表、视图或子查询。 然后,与此关系进行的所有联接都会使用倾斜联接优化。

-- table with skew
SELECT /*+ SKEW('orders') */
  *
  FROM orders, customers
  WHERE c_custId = o_custId

-- subquery with skew
SELECT /*+ SKEW('C1') */
  *
  FROM (SELECT * FROM customers WHERE c_custId < 100) C1, orders
  WHERE C1.c_custId = o_custId

使用关系名称和列名配置倾斜提示

一个关系可能有多个联接,只有其中一部分会受到倾斜的影响。 倾斜 join 优化会产生一些开销,因此建议仅在必要时使用。 为此,倾斜提示会接受列名。 只有使用这些列的联接才使用倾斜联接优化。

-- single column
SELECT /*+ SKEW('orders', 'o_custId') */
  *
  FROM orders, customers
  WHERE o_custId = c_custId

-- multiple columns
SELECT /*+ SKEW('orders', ('o_custId', 'o_storeRegionId')) */
  *
  FROM orders, customers
  WHERE o_custId = c_custId AND o_storeRegionId = c_regionId

使用关系名称、列名称和倾斜值配置倾斜提示

你还可以在提示中指定倾斜值。 根据查询和数据,倾斜 values 可能已知(例如,因为它们永远不会更改),或者可能很容易找到。这么做可以降低优化倾斜 join 的开销。 否则,Delta Lake 会自动检测它们。

-- single column, single skew value
SELECT /*+ SKEW('orders', 'o_custId', 0) */
  *
  FROM orders, customers
  WHERE o_custId = c_custId

-- single column, multiple skew values
SELECT /*+ SKEW('orders', 'o_custId', (0, 1, 2)) */
  *
  FROM orders, customers
  WHERE o_custId = c_custId

-- multiple columns, multiple skew values
SELECT /*+ SKEW('orders', ('o_custId', 'o_storeRegionId'), ((0, 1001), (1, 1002))) */
  *
  FROM orders, customers
  WHERE o_custId = c_custId AND o_storeRegionId = c_regionId