傾斜結合の最適化 Skew Join Optimization

データスキューとは、テーブルのデータがクラスター内のパーティション間で均等分散される条件です。Data skew is a condition in which a table’s data is unevenly distributed among partitions in the cluster. データスキューは、特に結合を使用したクエリのパフォーマンスを大幅にダウングレードする可能性があります。Data skew can severely downgrade performance of queries, especially those with joins. 大きなテーブル間の結合にはシャッフルデータが必要であり、スキューによってクラスター内での作業に極端な不均衡が生じる可能性があります。Joins between big tables require shuffling data and the skew can lead to an extreme imbalance of work in the cluster. クエリがスタックしていると思われる場合は、データスキューがクエリに影響を与える可能性があります (たとえば、200の最後の3つのタスク)。It’s likely that data skew is affecting a query if a query appears to be stuck finishing very few tasks (for example, the last 3 tasks out of 200). 検証するには:To verify:

  1. スタックしているステージをクリックし、結合を行っていることを確認します。Click the stage that is stuck and verify that it is doing a join.
  2. クエリが完了したら、結合を実行するステージを見つけて、タスク期間の分布を確認します。After the query finishes, find the stage that does a join and check the task duration distribution.
  3. 期間を短縮してタスクを並べ替え、最初のいくつかのタスクを確認します。Sort the tasks by decreasing duration and check the first few tasks. 1つのタスクが他のタスクよりも完了に時間がかかる場合、傾斜があります。If one task took much longer to complete than the other tasks, there is skew.

スキューを行うには、Azure Databricks SQL の Delta Lake で、クエリで_スキューヒント_を受け入れます。To ameliorate skew, Delta Lake on Azure Databricks SQL accepts skew hints in queries. Spark では、これらのヒントの情報を基に、データスキューの影響を受けない優れたクエリプランを構築できます。With the information from these hints, Spark can construct a better query plan, one that does not suffer from data skew.

関係名のみOnly relation name

_傾斜ヒント_には、少なくとも傾斜付きのリレーションシップ名が含まれている必要があります。A skew hint must contain at least the name of the relation with skew. リレーションシップは、テーブル、ビュー、またはサブクエリです。A relation is a table, view, or a subquery. このリレーションシップを持つすべての結合は、傾斜結合の最適化を使用します。All joins with this relation then use skew join optimization.

-- 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

リレーションシップと列Relation and columns

1つのリレーションシップに複数の結合が存在し、そのうちの一部だけが傾斜に影響を与える可能性があります。There might be multiple joins on a relation and only some of them will suffer from skew. 傾斜結合の最適化にはオーバーヘッドがあるため、必要な場合にのみ使用することをお勧めします。Skew join optimization has some overhead so it is better to use it only when needed. このため、_傾斜ヒント_は列名を受け取ります。For this purpose, the skew hint accepts column names. これらの列との結合でのみ、傾斜結合の最適化が使用されます。Only joins with these columns use skew join optimization.

-- 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

リレーション、列、および傾斜値Relation, columns, and skew values

ヒントに傾斜値を指定することもできます。You can also specify skew values in the hint. クエリとデータによっては、傾斜の値がわかっている場合があります (たとえば、変更されていないため)。または、わかりにくい場合があります。これにより、傾斜結合の最適化のオーバーヘッドが軽減されます。Depending on the query and data, the skew values might be known (for example, because they never change) or might be easy to find out. Doing this reduces the overhead of skew join optimization. それ以外の場合は、デルタレイクによって自動的に検出されます。Otherwise, Delta Lake detects them automatically.

-- 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