スキュー ヒントを使用したスキュー結合の最適化
重要
このドキュメントは廃止され、更新されない可能性があります。 このコンテンツで言及されている製品、サービス、テクノロジは、サポートされなくなりました。
スキュー結合ヒントは必要ありません。 Databricks は、アダプティブ クエリ実行 (AQE) を使って、既定でスキューを処理します。 「アダプティブ クエリの実行」を参照してください。
Note
spark.sql.adaptive.skewJoin.enabled
が True
である必要があります。これは、Azure Databricks での既定の設定です。
データ スキュー問題とは何ですか。
データ スキューは、テーブルのデータがクラスター内のパーティション間で不均等に分散される状態です。 データ スキューは、クエリ (特に結合を含むクエリ) のパフォーマンスを著しくダウングレードする可能性があります。 大きなテーブル間の結合にはデータのシャッフルが必要であり、スキューによってクラスター内の作業の極端な不均衡につながる場合があります。 クエリが非常に少数のタスク (たとえば、200 件中の最後の 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