スキューヒントを使用したスキュー結合の最適化
このドキュメントは廃止されており、更新されない可能性があります。 このコンテンツに記載されている製品、サービス、またはテクノロジはサポートされなくなりました。
スキュー結合ヒントは必要ありません。 Databricks は、アダプティブ クエリ実行 (AQE) を使用して、デフォルトによるスキューを処理します。 アダプティブ クエリの実行を参照してください。
spark.sql.adaptive.skewJoin.enabled
は True
にする必要があります。これは Databricks のデフォルト設定です。
データスキューとは?
データ スキューは、テーブルのデータがクラスター内のパーティション間で不均等に分散されている状態です。 データ スキューは、クエリ (特に結合を含むクエリ) のパフォーマンスを大幅に低下させる可能性があります。 大きなテーブル間の結合にはデータのシャッフルが必要であり、そのスキューにより、クラスターの作業が極端に不均衡になる可能性があります。 クエリが非常に少ないタスク (たとえば、200 個のタスクのうち最後の 3 個) の終了に止まっているように見える場合は、データ スキューがクエリに影響を与えている可能性があります。 データ スキューがクエリに影響を与えていることを確認するには、次のようにします。
- スタックしているステージをクリックし、ジョインを実行していることを確認します。
- クエリが完了したら、結合を実行するステージを見つけ、タスク期間の分布を確認します。
- タスクを期間の減少で並べ替え、最初のいくつかのタスクを確認します。 1 つのタスクの完了に他のタスクよりもはるかに長い時間がかかった場合は、スキューがあります。
スキューを改善するために、Databricks SQL 上の Delta Lake はクエリで スキュー ヒント を受け入れます。 スキュー ヒントからの情報を使用して、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