次の方法で共有


スキュー ヒントを使用したスキュー結合の最適化

重要

このドキュメントは廃止され、更新されない可能性があります。 このコンテンツに記載されている製品、サービス、またはテクノロジはサポートされなくなりました。

スキュー結合ヒントは不要です。 Databricks は、アダプティブ クエリ実行 (AQE) を使用して、既定でスキューを処理します。 アダプティブ クエリ実行を参照してください。

手記

spark.sql.adaptive.skewJoin.enabled Trueする必要があります。これは、Azure Databricks の既定の設定です。

データ スキューとは

データスキューは、テーブルのデータがクラスター内のパーティション間で不均一に分散される状態です。 データ スキューにより、クエリのパフォーマンス (特に結合があるクエリ) が大幅にダウングレードされる可能性があります。 大規模なテーブル間の結合にはデータのシャッフルが必要であり、スキューによってクラスター内の作業の負荷が極端に不均衡になる可能性があります。 クエリが非常に少数のタスク (たとえば、200 個中の最後の 3 つのタスク) を終了して停止しているように見える場合、データ スキューがクエリに影響を与える可能性があります。 データ スキューがクエリに影響していることを確認するには:

  1. スタックしているステージをクリックし、結合を実行していることを確認します。
  2. クエリが完了したら、結合を実行するステージを見つけて、タスク期間の分布を確認します。
  3. 期間を減らすことでタスクを並べ替え、最初のいくつかのタスクを確認します。 1 つのタスクの完了に他のタスクよりも長い時間がかかる場合は、傾斜があります。

スキューを改善するために、Delta Lake on Azure Databricks 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

リレーション名と列名を使用してスキュー ヒントを構成する

あるリレーションには複数の結合が存在する可能性があり、そのうちの一部だけが偏りの影響を受ける可能性があります。 スキュー結合の最適化にはオーバーヘッドがあるため、必要な場合にのみ使用することをお勧めします。 このため、スキュー ヒントでは列名を許可します。 スキュー結合の最適化を使用するのは、これらの列を持つ結合のみです。

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

関係名、列名、スキュー値を使用してスキュー ヒントを構成する

ヒントでスキュー値を指定することもできます。 クエリとデータによっては、スキュー値が認識される場合があります (変更されないためなど)。これを行うと、スキュー結合の最適化のオーバーヘッドが軽減されます。 それ以外の場合は、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