13

約 30 列と約 400,000 レコードを選択して別のテーブルに挿入する Hive クエリがあります。SQL 句に 1 つの結合がありますが、これは単なる内部結合です。

Java GC のオーバーヘッド制限を超えたため、クエリは失敗します。

奇妙なのは、結合句を削除して、テーブルからデータを選択するだけで (ボリュームが少し大きい)、クエリが正常に機能することです。

私はハイブにかなり慣れていません。この結合によってメモリ例外が発生する理由がわかりません。

これらの問題が発生しないように、Hive クエリを記述する方法に関して注意すべき点はありますか? 結合がこの問題を引き起こす可能性がある理由を誰かが説明できますが、より多くのデータと同じ数の列を選択してもそうではありません。

これについてのあなたの考えに感謝します。ありがとう

4

2 に答える 2

41

Hive のバージョンと構成によっては、質問に対する答えが異なる場合があります。正確なクエリと、2 つのテーブルの作成ステートメントおよびそれらのサイズの見積もりを共有できれば、より簡単になります。

問題をよりよく理解するために、「通常の」内部結合が Hive でどのように機能するかを見てみましょう。

MapReduce での Hive の結合:

以下は、Hive の内部結合が MapReduce にコンパイルされる方法を簡単に説明したものです。一般に、次のような結合クエリを持つ 2 つのテーブル t1 と t2 があるとします。

SELECT
   t1.key, t1.value, t2.value
FROM
   t1
   JOIN
   t2 (ON t1.key = t2.key);

ここで、t1 の内容は次のとおりです。

k_1    v1_1
k_2    v1_2
k_3    v1_3    

ここで、t2 の内容は次のとおりです。

k_2    v2_2
k_3    v2_3
k_4    v2_4    

結合結果は次のようになると予想されます

k_2    v1_2    v2_2
k_3    v1_3    v2_3

テーブルが HDFS に保存されていると仮定すると、その内容はファイル分割に分割されます。マッパーはファイル分割を入力として受け取り、キーをテーブルのキー列として出力し、値をテーブルの値列とフラグの複合体として出力します (レコードがどのテーブルからのものか、つまり t1 または t2 を表します)。 .

t1 の場合:

k_1, <v1_1, t1>
k_2, <v1_2, t1>
k_3, <v1_3, t1>

t2 の場合:

k_2, <v2_2, t2>
k_3, <v2_3, t2>
k_4, <v2_4, t2>

ここで、これらの出力されたレコードは、同じキーを持つすべてのレコードがグループ化されてレデューサーに送信されるシャッフル フェーズを通過します。各縮小操作のコンテキストは、1 つのキーと、そのキーに対応するすべての値を含むリストです。実際には、1 つのレデューサーが複数のリデュース操作を実行します。

上記の例では、次のグループ化が得られます。

k_1, <<v1_1, t1>>
k_2, <<v1_2, t1>, <v2_2, t2>>
k_3, <<v1_3, t1>, <v2_3, t2>>
k_4, <<v2_4, t2>>

レデューサーで何が起こるかを次に示します。値のリスト内の各値について、値が異なるテーブルに対応する場合、リデューサーは乗算を実行します。

k_1 の場合、t2 からの値はなく、何も出力されません。

k_2 の場合、値の乗算が発行されます - k_2、v1_2、v2_2 (各テーブルから 1 つの値があるため、1x1 = 1)

k_3 の場合、値の乗算が発行されます - k_3、v1_3、v2_3 (各テーブルから 1 つの値があるため、1x1 = 1)

k_4 の場合、t1 からの値はなく、何も出力されません。したがって、内部結合から期待した結果が得られます。

わかりました、それで私は何をしますか?

  1. データに偏りがある可能性があります。言い換えると、リデューサーがデータを取得するときに、あるキーに対応する値のリストが非常に長く、エラーが発生します。この問題を軽減するには、JVM で使用できるメモリを増やしてみてください。hive-site.xml のmapred.child.java.optsような値に設定することで、これを行うことができます。Hive シェルで-Xmx512M実行することにより、このパラメーターの現在の値を照会できます。set mapred.child.java.opts;

  2. マップ結合など、「通常の」結合に代わる方法を試すことができます。上記の結合の説明は、結合がレデューサーで発生する通常の結合に適用されます。使用している Hive のバージョンによっては、Hive が通常の結合をより高速なマップ結合に自動的に変換できる場合があります (結合はマップ フェーズで発生するため)。最適化を有効にするには、 に設定hive.auto.convert.jointrueます。このプロパティはHive 0.7で導入されました

  3. に設定hive.auto.convert.joinする以外に、 に設定するtrueこともできます。これにより、1 で説明したデータの偏りの問題を回避できます。hive.optimize.skewjointrue

于 2012-07-10T02:32:42.063 に答える
5

応答マークに感謝します。とても有難い。

何時間も経った後、結合ステートメント内のテーブルの順序が違いを生むことが最終的にわかりました。最適なパフォーマンスとメモリ管理のために、最後の結合は最大のテーブルにする必要があります。

結合ステートメントでテーブルの順序を変更すると、問題が修正されました。

http://hive.apache.org/docs/r0.9.0/language_manual/joins.htmlで、Largest Table Last を参照してください。

上記の説明も非常に役立ちます。どうもありがとう

于 2012-07-10T03:40:19.670 に答える