私はHiveの2つの大きなテーブルを結合しています(1つは10億行を超え、1つは約1億行です)。
create table joinedTable as select t1.id, ... from t1 join t2 ON (t1.id = t2.id);
2つのテーブルを同じ方法でバケット化し、IDでクラスタリングしてそれぞれ100バケットにしましたが、クエリにはまだ長い時間がかかります。
これをスピードアップする方法に関する提案はありますか?
結合キーでデータをバケット化したので、バケットマップ結合を使用できます。そのため、1つのテーブルのバケット数は、他のテーブルのバケット数の倍数である必要があります。クエリの前にset Hive.optimize.bucketmapjoin=true;
を実行することでアクティブ化できます。テーブルが条件を満たさない場合、Hiveは通常の内部結合を実行します。
両方のテーブルに同じ数のバケットがあり、データがバケットキーでソートされている場合、Hiveはより高速なソート/マージ結合を実行できます。これをアクティブにするには、次のコマンドを実行する必要があります。
set Hive.input.format=org.Apache.hadoop.Hive.ql.io.BucketizedHiveInputFormat;
set Hive.optimize.bucketmapjoin=true;
set Hive.optimize.bucketmapjoin.sortedmerge=true;
https://cwiki.Apache.org/confluence/download/attachments/27362054/Hive+Summit+2011-join.pdf で、さまざまな結合技術のいくつかの視覚化を見つけることができます。
私が見ると、答えは@Adrian Langeが提供したものよりも少し複雑です。
最初に、BucketJoinとSort-Merge Bucket Join(SMBJ)の非常に重要な違いを理解する必要があります。
bucketjoinを実行するには、前述のように、「1つのテーブルのバケット数は、他のテーブルのバケット数の倍数である必要があります」、さらにHive.optimize.bucketmapjoin
をtrueに設定する必要があります。
結合を発行すると、Hiveはそれをbucketjoinに変換します。上記の条件が発生した場合[〜#〜] but [〜#〜] Hiveはバケット化を強制しません!これは、HiveがHive.enforce.bucketing
がtrueに設定されていない(つまり、実際にバケットの数がテーブルにデータを挿入するクエリの最終段階でのレデューサーの量)。
パフォーマンスの面から、bucketjoin a single taskを使用する場合、マッパーがアクセスする前に「小さい」テーブルを分散キャッシュに読み込むことに注意してくださいそして、結合を実行します-このステージは、テーブルが1億行以下の場合、おそらく非常に長く、効果がありません。
病棟後、レジューサーで行われる通常のジョインと同じようにジョインが行われます。
[〜#〜] smbj [〜#〜]を実行するには、Hive.optimize.bucketmapjoin.sortedmerge
をtrueに設定することに加えて、両方のテーブルで同じ列にまったく同じ量のバケットを持ち、これらの列で並べ替える必要があります。
以前の最適化と同様に、Hiveはバケット化と並べ替えを強制せず、テーブルが実際にバケット化および並べ替えられていることを前提としています(定義だけでなく、Hive.enforce.sorting
を設定するか、データを手動で並べ替えることによってそれを挿入する)-これは非常に重要です両方のケースで間違った結果につながる可能性があります。
performace側と同様に、この最適化は、次の理由によりはるかに効率的です。
以下の考慮事項に注意してください。
set Hive.input.format=org.Apache.hadoop.Hive.ql.io.BucketizedHiveInputFormat;
/*+ MAPJOIN(b) */
をクエリに適用する必要があります(select
の直後、b
は小さいテーブルです)また、これらの最適化だけでは常に高速なクエリ時間が保証されるわけではないことを忘れないでください。
SMBJを実行することを選択したとしましょう。これにより、結合を実行する前に2つのテーブルをソートするコストが追加されます。そのため、クエリを実行する回数が増えるほど、このソートステージに対する「支払い」が少なくなります。
場合によっては、単純な結合で最高のパフォーマンスが得られ、上記の最適化のいずれも役に立たないため、アプリケーション/論理レベルで、またはメモリ使用量/並列処理などのMapReduce/Hive設定を調整して、通常の結合プロセスを最適化する必要があります。
マップバケット結合では、「1つのテーブル内のバケットの量は、他のテーブル内のバケットの数の倍数でなければならない」という基準が必要だとは思いません。同じ数のバケットを使用することもできます。