ロングテールは、JOIN 操作やその他のコンピューティングジョブで発生する可能性があります。このトピックでは、ロングテールが発生するシナリオと解決策について説明します。
ロングテールは、分散コンピューティングにおける一般的な問題の 1 つです。ロングテールの主な原因は、不均一なデータ分布です。その結果、個々のノードのワークロードが異なります。ジョブ全体は、最も遅いノードがすべてのデータを処理し終えた後にのみ完了します。
1 つのワーカーに処理が集中しないように、ジョブを複数のワーカーに分散させる必要があります。
GROUP BY ロングテール
原因
GROUP BY 句のキーに対するコンピューティングワークロードが重い場合に発生します。
ソリューション
- SQL ステートメントを書き換えてランダムな値を追加し、スキューしたキーを分割します (ソルティングと呼ばれる手法)。例:
SELECT Key, COUNT(*) AS Cnt FROM TableName GROUP BY Key;コンバイナがない場合、マッパーはデータをリデューサーにシャッフルし、リデューサーが COUNT 操作を実行します。対応する実行計画は、マッパー > リデューサーです。スキューしたキーの処理を再分散させるには、次のようにクエリを書き換えます。
-- スキューしたキーが「KEY001」であると仮定します。 SELECT a.Key , SUM(a.Cnt) AS Cnt FROM ( SELECT Key , COUNT(*) AS Cnt FROM TableName GROUP BY Key, CASE WHEN Key = 'KEY001' THEN Hash(Random()) % 50 ELSE 0 END ) a GROUP BY a.Key;実行計画は、マッパー > リデューサー > リデューサーになります。これによりステージが 1 つ追加されますが、スキューしたキーを 2 つのステージで処理することで、全体の実行時間を短縮できます。
説明 データスキューが深刻でない場合、この方法は不要なリデューサー ステージを追加してしまい、全体の実行時間が増加する可能性があります。 - システム パラメータを設定してロングテールの問題を解決します。
set odps.sql.groupby.skewindata=true;この設定により、汎用的な最適化が有効になります。ビジネスロジックを分析しないため、実行計画が最適ではない可能性があります。最高のパフォーマンスを得るには、データの分布に基づいて SQL クエリを書き換えてください。
DISTINCT ロングテール
DISTINCT キーワードでロングテールが発生した場合、キー分割方法は適用できません。この場合、他の方法を検討する必要があります。
ソリューション
-- 元の SQL ステートメント。uid が指定されていないケースに関係なく。
SELECT COUNT(uid) AS Pv
, COUNT(DISTINCT uid) AS Uv
FROM UserLog;
SELECT SUM(PV) AS Pv
, COUNT(*) AS UV
FROM (
SELECT COUNT(*) AS Pv
, uid
FROM UserLog
GROUP BY uid
) a;
この方法は、DISTINCT を GROUP BY に変更するものです。これにより、計算ワークロードが複数のリデューサーに分散されます。ステートメントを書き換えると、GROUP BY の最適化方法を使用でき、コンバイナも計算に関与するようになるため、パフォーマンスが大幅に向上します。
動的パーティションにおけるロングテール
原因
- 小さいファイルのデータをソートするために、動的パーティション機能は実行の最終ステージでリデューサーを起動します。動的パーティション機能を使用して書き込まれたデータが偏っている場合、ロングテールが発生します。
- 一般的に、動的パーティション機能の不適切な使用がロングテールの原因となります。
ソリューション
データを書き込むパーティションがわかっている場合は、動的パーティションを使用する代わりに、データを挿入する前にパーティションを指定できます。
コンバイナを使用したロングテールの処理
コンバイナは、MapReduce ジョブでロングテールを処理するために頻繁に使用されます。コンバイナを使用すると、マッパーからリデューサーにシャッフルする必要があるデータ量を削減できます。これにより、ネットワーク伝送のオーバーヘッドが大幅に削減されます。この最適化は、MaxCompute SQL で自動的に実装されます。
(key, 1) ペアを受け取る場合と、コンバイナがそれらを 1 つの(key, 2) ペアに事前集計する場合のどちらであっても、最終結果は同じです。ただし、平均を計算するような操作では、コンバイナは最終的なリデュース処理の前に(key, 1) と(key, 2) を(key, 1.5) に結合することはできません。システムによるロングテール最適化
コンバイナに加えて、MaxCompute には他の最適化も実装されています。たとえば、ジョブの実行中に次のようなログが生成されることがあります。
M1_Stg1_job0:0/521/521[100%] M2_Stg1_job0:0/1/1[100%] J9_1_2_Stg5_job0:0/523/523[100%] J3_1_2_Stg1_job0:0/523/523[100%] R6_3_9_Stg2_job0:1/1046/1047[100%]
M1_Stg1_job0:0/521/521[100%] M2_Stg1_job0:0/1/1[100%] J9_1_2_Stg5_job0:0/523/523[100%] J3_1_2_Stg1_job0:0/523/523[100%] R6_3_9_Stg2_job0:1/1046/1047[100%]
M1_Stg1_job0:0/521/521[100%] M2_Stg1_job0:0/1/1[100%] J9_1_2_Stg5_job0:0/523/523[100%] J3_1_2_Stg1_job0:0/523/523[100%] R6_3_9_Stg2_job0:1/1046/1047(+1 backups)[100%]
M1_Stg1_job0:0/521/521[100%] M2_Stg1_job0:0/1/1[100%] J9_1_2_Stg5_job0:0/523/523[100%] J3_1_2_Stg1_job0:0/523/523[100%] R6_3_9_Stg2_job0:1/1046/1047(+1 backups)[100%]
合計 1,047 個のリデューサーが使用されます。1,047 個のリデューサーのうち 1,046 個は計算を完了しましたが、最後の 1 つは完了していません。MaxCompute がこの問題を検出すると、自動的に新しいリデューサーを起動して同じデータを計算させ、先に計算を完了した方のリデューサーの結果を最終結果セットに集約します。
ビジネスロジックの最適化によるロングテールへの対処
前述の最適化方法では、すべてのロングテールを処理できるわけではありません。場合によっては、ロングテールに対処するためにビジネスロジックを最適化する必要があります。
- 計算対象のデータに、大量のノイズデータが含まれている可能性があります。たとえば、訪問者IDに基づいてデータを集計し、各ユーザーのアクセス記録を確認する場合、クローラーデータをフィルタリングする必要があります。そうしないと、計算中にクローラーデータが原因でロングテールが発生する可能性があります。クローラーデータの識別は、ますます困難になっています。同様に、xxid フィールドを関連付けに使用する場合は、関連付けるフィールドが空でないことを確認する必要があります。
- 特定のビジネス シナリオでは、ロングテールが発生する可能性があります。たとえば、独立系ソフトウェアベンダー (ISV) の操作記録は、データ量と動作の点で個人の記録と大きく異なります。この場合、重要な顧客に起因する問題を処理するために、特定の分析方法を使用する必要があります。
- データの分散に偏りがある場合、すべてのデータ レコードをソートするために DISTRIBUTE BY のキーとして定数を使用しないことを推奨します。