1日を失うことをお勧めしますが、その後5分(s )
こんにちは同僚。
HadoopエコシステムのHiveとPigフレームワークがどのように異なるかについて、いくつかの考えを共有したいと思います。 実際、これらは非常によく似た2つの製品であり、その目的は同じです。MapReduceの技術実装全体を引き受け、データ処理プロセスをより抽象的なレベルで説明する機会を提供します。 この記事では、これら2つのシステムでサンプルがどのように見えるかを確認し、どのケースで1つまたは別のソリューションを使用すべきかを理解しようとします。
ハイブ
それでは、Hiveから始めましょう。 その主な機能は、SQLに似たHQLクエリ言語です。 これにより、通常のリレーショナルデータベースを操作しているかのように、使い慣れた方法でデータを操作できます。 スクリプトは、コンソールまたはコマンドラインを使用して実行できます。
ハイブは:
- SQLのようなHQL
- インタラクティブコンソール
- 組み込みの集計関数
- ユーザー機能サポート(UDF)
- データは表のようなものです
Hiveは機能します。
- テキストファイル(区切り文字を指定できます)
- 圧縮されたテキストファイル(Gzip、Bzip)
- 配列、辞書、ユニオン(ユニオン)
- コレクション、日付、文字列、JSONを操作するための膨大な数の組み込み関数があります
- 数学関数(四捨五入、対数、根、三角法)
- 集約関数(合計、最小、最大、平均...)
- 上記のすべてが十分でない場合は、カスタム関数、およびマッパーとリデューサー(python、java)を使用できます
簡単な例:
-- . ( ) CREATE EXTERNAL TABLE win_bids_log ( date_field string, request_id string, user_ssp_id string, dsp_id string, win_price int ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION 'hdfs://inpit/bid-logs'; CREATE EXTERNAL TABLE win_bids_by_dsp ( dsp_id string, win_bids_cout int, win_price int ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' STORED AS TEXTFILE LOCATION ''hdfs://output/win-bids-by-dsp''; INSERT OVERWRITE TABLE win_bids_by_dsp SELECT dsp_id, COUNT(dsp_id), SUM(win_price) FROM win_bids_log GROUP BY dsp_id;
ご覧のとおり、すべてが非常にシンプルで明確です。 おなじみの言語でクエリを書くのはとてもいいことです。 しかし、この幸せは、より複雑な要求に対処するまで続きます。
例はもっと複雑です:
INSERT OVERWRITE TABLE movieapp_log_stage SELECT * FROM ( SELECT custid, movieid, CASE WHEN genreid > 0 THEN genreid ELSE -1 END genreid, time, CAST((CASE recommended WHEN 'Y' THEN 1 ELSE 0 END) AS INT) recommended, activity, CAST(null AS INT) rating, price FROM movieapp_log_avro WHERE activity IN (2,4,5,11) UNION ALL SELECT m1.custid, m1.movieid, CASE WHEN m1.genreid > 0 THEN m1.genreid ELSE -1 END genreid, m1.time, CAST((CASE m1.recommended WHEN 'Y' THEN 1 ELSE 0 END) AS INT) recommended, m1.activity, m1.rating, CAST(null as float) price FROM movieapp_log_avro m1 JOIN ( SELECT custid,movieid, CASE WHEN genreid > 0 THEN genreid ELSE -1 END genreid,MAX(time) max_time, activity FROM movieapp_log_avro GROUP BY custid, movieid, genreid, activity ) m2 ON ( m1.custid = m2.custid AND m1.movieid = m2.movieid AND m1.genreid = m2.genreid AND m1.time = m2.max_time AND m1.activity = 1 AND m2.activity = 1 ) ) union_result;
もちろん、あなたはそれを理解することができますが、それでもこの場合には間違いなく秩序の欠如があることを認識する価値があります。 それをすべて棚に置きますが、コメントを付けてください。 そう?
合計:
Hiveの長所:
- 古き良きSQLは、サンプルの記述に適しています。 はい、そして誰もが彼を知っています。
- 内部のMapReduce。 MRのストラッピングに関連する多くのオーバーヘッドがかかります。 データモデル、入力および出力形式、MRタスクチェーンの説明。
- 双方向性 異なるスライスのデータを分析するのに適しています。
- 開発スピード
- 依存関係、コンパイル、アセンブリの欠如(これはすべて隠されています)
ハイブの短所:
- すべてをHQLパラダイムに入れることはできません
- 簡単なサンプルに適しています。 しかし、複雑さが増すにつれて、それらを理解することはますます難しくなります。 特にサンプルを書いていない場合
豚
それでは豚について話しましょう。 これは、手続き言語のPig Latinに基づいています。 それを理解するためには、しばらく時間をかける必要があります。
それを理解して、Hiveとの違いを見つけましょう
豚は:
- 豚のラテン
- インタラクティブコンソール
- 組み込みの集計関数
- ユーザー機能サポート(UDF)
- データ-構造の形式(タプル、バッグ)
ブタが機能します:
- テキストファイル(区切り文字を指定できます)
- 圧縮されたテキストファイル(Gzip、Bzip)
- 配列、辞書、ユニオン(ユニオン)
- 日付、文字列、構造体を扱うための膨大な数の組み込み関数があります。
- 数学関数(四捨五入、対数、根、三角法)
- 集約関数(合計、最小、最大、平均...)
- 上記のすべてが十分でない場合は、カスタム関数(jython、java)を使用できます
ご覧のとおり、PigはHiveと同じことができます。 唯一の違いは、データの表示と言語です。 しかし、Pigをまったく新しいレベルに引き上げるのはまさにこの違いです。
Pigを詳しく見てみましょう。
このフレームワークは、特別なデータ構造(タプルとバッグ)で機能します。
- タプルは、順序付けられたフィールドのセットです。 インデックスおよび/または名前でフィールドにアクセスできる構造。
- バッグ -タプルのコレクション(セット)。
豚ラテン語の基本機能:
- LOAD
- 店舗
- 生成
- 参加する
- グループ
- フィルター
- UNION
- 明確な
- ご注文
Pigを使用するプロセスでデータを変換する方法の例を見てみましょう。 RTB交換のログファイルを使用します。 データは次のように表示されます。
- 時間 -時間
- bid_id-入札識別子、
- user_id-ユーザーID
- dsp_id-入札者(プレーヤー)の識別子
- 入札 -入札
豚-データの読み込み(LOAD)
LOAD関数は読み込みに使用され、区切り文字「\ t」とデータ署名も指定します(必要に応じてタイプを指定できます)。
-- HDFS (Pig Hadoop) fs -rm -f -r -skipTrash /data/pig/out -- 'raw_data' raw_data = LOAD '/data/pig/example/' USING PigStorage('\t') AS (time, bid_id, user_id, dsp_id, bid:int);
出力では、まさにそのような構造(タプル)を取得します。 クエリでは、そのフィールドにはドットを介してアクセスできます。 例:raw_data.dsp_id
raw_data -> tuple . ------------------------------------------------------------------------------------------- time, bid_id, user_id, dsp_id, bid ------------------------------------------------------------------------------------------- (2014.02.14 14:08:27.711, 56949, 45234534553459, DSP-2, 12) (2014.02.14 14:08:28.712, 61336, 45221696259999, DSP-1, 56) (2014.02.14 14:08:29.713, 74685, 45221699381039, DSP-2, 89) (2014.02.14 14:08:30.714, 56949, 45221695781716, DSP-1, 21) (2014.02.14 14:08:25.715, 27617, 45221682863705, DSP-3, 22)
豚-反復データ処理(FOREACH-GENERATE)
FOREACH-GENERATEを使用すると、データセットを繰り返し「実行」し、各レコードに操作を適用したり、特定のフィールドを出力に送信して、不要なものをすべて削除したりできます。
-- . timestamp SUBSTRING norm_data = FOREACH raw_data GENERATE SUBSTRING(time, 0,10) AS date, dsp_id, bid;
出力では、同じセットが取得されますが、日付は切り捨てられ、dsp_id、bidの2つのフィールドのみがあります。
norm_data -> tuple --------------------------------------- date, dsp_id, bid --------------------------------------- (2014.02.14, DSP-2, 12) (2014.02.14, DSP-1, 56) (2014.02.14, DSP-2, 89) (2014.02.14, DSP-1, 21)
豚-データのグループ化(GROUP)
GROUP-自明ではない構造を提供しながら、データをグループ化できます。
-- dsp_id date group_norm_data = GROUP norm_data BY (dsp_id, date);
出力には次のものがあります。
キーとしてのグループ。 グループプレフィックスを介してアクセスできます。
そして、norm_dataで始まる集約のコレクション
group_norm_data -> ( ) : [ (norm_data), (norm_data) ] ---------------------------------------------------------------------------------- ( group), array of norm_data ---------------------------------------------------------------------------------- ( (DSP-1, 2014.02.14), {(2014.02.14, DSP-1, 56), (2014.02.14, DSP-1, 21)} ) ( (DSP-1, 2014.02.17), {(2014.02.17, DSP-1, 34), (2014.02.17, DSP-1, 24)} ) ( (DSP-2, 2014.02.14), {(2014.02.14, DSP-2, 89), (2014.02.14, DSP-2, 12)} )
豚-集約スイープ(フラッテン)
集合体を線形構造で展開する必要がある場合があります(「まっすぐに」)。
これにはFLATTEN関数があります。
-- ft_group_norm_data = FOREACH group_norm_data GENERATE FLATTEN(group), FLATTEN(norm_data);
複雑なグループ構造から、簡単な組のタプルを取得します。
ft_group_norm_data -> tuple ---------------------------------------------------------------------- dsp_id, date date dsp_id bid ----------------------------------------------------------------------- (DSP-1, 2014.02.14, 2014.02.14, DSP-1, 56) (DSP-1, 2014.02.14, 2014.02.14, DSP-1, 21) (DSP-1, 2014.02.15, 2014.02.15, DSP-1, 15) (DSP-1, 2014.02.15, 2014.02.15, DSP-1, 31)
豚-集約関数(SUM)
数えましょう。 たとえば、各入札者による1日の賭け金。
-- , sum_bids_dsp = FOREACH group_norm_data GENERATE group, SUM(norm_data.bid) AS bids_sum;
sum_bids_dsp -> : bids_sum ------------------------------------------------------ group, bids_sum ------------------------------------------------------ ( (DSP-1, 2014.02.16), 82) ( (DSP-1, 2014.02.17), 58) ( (DSP-2, 2014.02.14), 101) ( (DSP-2, 2014.02.16), 58)
豚-グループすべて
多くの場合、サンプルの「レコード」の数を計算する必要があります。 選択にCOUNTを適用するだけでは失敗します。 データを1つのグループにまとめてから、集約関数を適用する必要があります。
-- , . -- . group_all = GROUP sum_bids_dsp ALL;
出力には、「すべて」グループと以前のすべてのユニットのコレクションがあります。
( all, { ((DSP-1,2014.02.14),77), ((DSP-1,2014.02.15),67), ((DSP-1,2014.02.16),82),((DSP-1,2014.02.17),58),((DSP-2,2014.02.14),101),((DSP-2,2014.02.16),58),((DSP-2,2014.02.17),123),((DSP-3,2014.02.14),22),((DSP-3,2014.02.15),109),((DSP-3,2014.02.16),136),((DSP-3,2014.02.17),81) } )
次に、金額と金額を計算します
summary = FOREACH group_all GENERATE COUNT(sum_bids_dsp), SUM(sum_bids_dsp.bids_sum);
出口
------------------------------------------------------ count, sum ------------------------------------------------------ (11, 914)
私の意見では、これがあなたが必要とするものです。 データ処理は順番に表示されます。 すべてが簡単にステップに分割されます。 各ステージにはコメントを付けることができます。
合計:
豚の長所:
- 手続き的アプローチ。 秩序! この言語を使用すると、ロジックをブロックに分割でき、各ステップをコメントで詳細に説明できます。
- 内部のMapReduceフォーメーション。 MRのストラッピングに関連する多くのオーバーヘッドがかかります。 データモデル、入力および出力形式、MRタスクチェーンの説明。
- 双方向性 異なるスライスのデータを分析するのに適しています。
- 開発のスピード。 依存関係なし、ビルド
豚の短所:
- すべてをPig Latinに入れることができるわけではありません
- HQLとは異なり、データ構造を持つブタラテン語はより複雑です
- UDFの場合、Jythonが使用されます。 これにより、一部のライブラリの使用が制限される場合があります。
要約:
- Hiveは、小さくて複雑でないサンプルに適しています。 HQLはSQLに似ているため、このフレームワークをすぐに使用できます。
- 豚言語とデータ構造を学ぶ必要があります。 しかし、それを理解すると、複雑で多段階のサンプルを簡単に実装できる、より強力なツールが手に入ります。 アクセス可能で関連性のあるコメントを含む、シンプルで整然としたコードを取得します。
あなたとあなたの同僚がSQLをよく知っていて、毎日SQLを使用していて、激しいクエリに戸惑うことがなければ、Hiveは素晴らしいソリューションです。 ただし、SQLをときどき使用していて、データワークフローが単純なクエリに適合しない場合は、間違いなく1日をかけてPigを整理する価値があります。 将来的には、これにより多くの時間と同僚を節約できます。