次の方法で共有


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

重要

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

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

Note

spark.sql.adaptive.skewJoin.enabledTrue である必要があります。これは、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

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

1 つの関係に複数の結合が存在する場合があり、一部の結合だけがスキューの影響を受ける可能性があります。 スキュー結合の最適化にはある程度のオーバーヘッドがあるので、必要な場合にのみ使用することをお勧めします。 このため、スキュー ヒントでは列名を許可します。 これらの列を含む結合でのみ、スキュー結合の最適化が使用されます。

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