ポイント: Apache Pigは、Hadoopにおけるデータ処理をSQLのような構文で簡素化し、直感的な操作のためにタプルやバッグのようなデータ構造を使用します。
- Yahooによって開発され、Hadoopのデータ処理を効率化します。
- 主要な操作には、データの効果的な取り扱いのためのLOAD、GROUP、FOREACHが含まれます。
Apache Pig 101
Apache PigはYahooで開発され、Hadoopを扱いやすくするために書かれました。HadoopはGoogleによって開発されました。Pigを使用すると、プログラマーはSQLに似た構文を使用してHadoopデータセットを操作できます。Pigがなければ、プログラマーは通常、Hadoopが書かれているJavaを使用します。しかし、Javaコードは本質的に冗長です。Hadoop MapReduce操作を行うための簡単で短い方法があれば良いのですが、それがPigの役割です。
ただし、PigはSQLそのものではありません。実際、SQLプログラマーはそのデータ構造のいくつかが少し奇妙だと感じるでしょう。
Pigのデータは、すべての他のPigデータ構造がその変種であるタプルと呼ばれるデータ構造で表されます。最も基本的な形では、タプルはカンマで区切られた値のセットです:
(1,2,3,4,5)
(1,6,7,8,9)
そして、2つのタプルを結合すると、最初の要素でデータが次のように表されます:
またはこれ:
(1,2,3,4,5,1,6,7,8,9)
またはこれ:
(1, {(1,2,3,4,5), (1,2,3,4,5)})
最初のケースでは、Pigは2つのタプルのすべての要素を1つに結合しました。2番目のケースでは、結合基準を最初の要素に置き、2番目にバッグを作成しました。バッグはタプルのコレクションです。個々の要素は原子と呼ばれます。Pigはまた、(key#value)形式のマップもサポートしています。
これらの奇妙な構造は、プログラマーを困惑させ、個々の原子をクエリする方法を考えるのに苦労させます。以下にいくつかの操作を説明します。
Pigの使用とその動作
Pigの役割は、データセットに対してMapReduce操作を実行することです。MapReduceはHadoopおよびビッグデータの基本概念ですが、HadoopとApache SparkやScalaプログラミング言語では意味が異なります。Hadoopでは、map操作はデータセットを部分に分割し、それらの部分を並行して処理することを意味します。Reduceは、それらをすべて元に戻して目的のデータセットを提供します。SparkやScalaでは、mapはリスト内の各要素に対して何らかの操作を実行することを意味し、Reduceはそれらの操作から最終的な単一値を計算します。
Pigをローカルモデルで開始するには、次のようにします:
pig -x local
ただのPigの代わりに:
pig
これにより、クラスタ(別名mapReduce)モードで実行されます。ローカルモデルは分散アーキテクチャをシミュレートします。クラスターモードでは、mapReduceはApache Yarnを使用してクラスタ(すなわち、機械のネットワーク)上でジョブを実行し、結果のデータをHDFS(Hadoop分散ファイルシステム)に保存します。
一般的な間違い
Pigには、デバッグエラーが難しい独特の特徴があります。また、Pigを維持する人々は言語を少しずつ変更し続けています。通常、シンプルなエラーメッセージは表示されず、ほとんどの場合、長くて読みづらいJavaスタックトレースが表示されます。(それは現在のディレクトリにtmp*ファイルとして保存されます。)したがって、いくつかのコード例を見始める前に、問題やフラストレーションを引き起こす可能性のある一般的な間違いをいくつか見てみましょう:
- HDFSがどのポートで実行されているか確認し、そこにファイルを開く必要があります。$HADOOP_HOME/etc/hadoop/core-site.xmlでfs.default.namehdfs://localhost:9000を確認し、ポート番号を取得します。
- Google Docsや他のワードプロセッサからPigシェルに左側の引用符をコピー&ペーストする際には注意してください。Pigは適切なシングルクォート(ASCII 27)を使用しない限りエラーをスローします。
- Pigをrootとして実行するか、パーミッションの問題を整理するのに時間をかける必要があります。
- 不完全なコマンドを入力するときに(control)(-c-)を使用しないでください。入力を促します。それがシェルを終了します。現在のコマンドを終了するまで「,」や「;」を入力してください。それにはかなりの試行回数がかかることがあります。
- テキストエディタでコマンドを入力し、Pigにペーストします。Pigは以前のコマンドを簡単に編集できないためです。たとえば、折り返す場合、上矢印カーソルを使用して以前の行を編集することはできません。historyと入力することでコマンドの履歴を表示できます。
- ラップトップにHadoopとPigをインストールして学習する場合は、pig -x localと入力してローカルモードで実行します。java.net.ConnectExceptionエラーが表示される場合、それはYarnまたは他のサービスが実行されていないか、適切に構成されていない可能性があります。
- Pigを簡単だと呼んでも、苛立たしいことがあります。たとえば、この文書を書く際に、storeは予約語であり、列名として使用できないことがわかりました。そのため、以下に示す売上レポートを書くのには時間がかかりました。Pigは「storeは予約語です」といった親切なエラーメッセージを表示しませんでした。
ファイルをロード
sales.csvというデータファイルがあり、従業員ごとのショップの売上があるとします。(先ほど述べたように、予約語であるため、列名としてstoreを使用できません。したがって、shopを使用します。)
ショップ、従業員、売上
Dallas,Sam,30000
Dallas,Fred,40000
Dallas,Jane,20000
Houston,Jim,75000
Houston,Bob,65000
New York,Earl,40000
Pigを使用して店舗ごとの売上を計算できます。まず、ヘッダーを含む最初の行を削除します。そうしないと、データセット内の行になります。その後、ファイルを次のようにHadoop分散ファイルシステムにコピーします:
hdfs dfs -put sales.csv /user/hadoop/
次に、データセットaにロードします。Pigでは、データセットは関係と呼ばれます。ここで、入力ファイルがカンマ区切りであることを指定し、ASを使用してデータセットにスキーマを割り当てます。また、フィールドタイプを指定します:chararrayおよびint。
a = LOAD 'hdfs://localhost:9000/user/hadoop/sales.csv' USING PigStorage(',') AS (shop:chararray,employee:chararray,sales:int);
次に、次のようなタプルがあります。これは次のように入力することで見ることができます:
dump a
(Dallas,Sam,30000)
(Dallas,Fred,40000)
(Dallas,Jane,20000)
(Houston,Jim,75000)
(Houston,Bob,65000)
(New York,Earl,40000)
関係内のスキーマを省略することもできたことに注意してください。その場合、フィールドは相対的な位置$0、$1、$2で参照します。また、Pigは遅延実行されると言われています。つまり、必要になるまでmapReduce関数は実行されません。たとえば、データをdumpで印刷するときです。
Pigにデータセットのスキーマを表示するように要求します:
describe a
a: {shop: chararray,employee: chararray,sales: int}
今、データをショップごとにグループ化します。
b = GROUP a BY shop;
次に、count、sum、またはaverageのようなグループ操作を実行します:
c = FOREACH b GENERATE group as shop, SUM (a.sales);
これにより、各ショップの売上合計が得られます:
(Dallas,90000)
(Houston,140000)
(New York,40000)
売上列をa.salesとして参照したことに注意してください。b関係を作成した後でも。
ForEach
Pigを使用すると、FOREACH構文でタプル内の要素に対してユーザー定義関数(UDF)を定義できます。それらをPig、Python、Rubyなどでコーディングできます。その他の人が書いて寄付したPiggy Bank関数を使用することもできます。ここやDataFuを使用することもできます。Pigには組み込み関数があまりないため、人々は自分のものを追加しています。
しかし、簡単な算術はできます。たとえば、ここでは、各売上数字を2倍にして新しいデータセットbを作成します。元のデータセットaから2つのフィールドだけを取得して、1つの列を削除したことにも注意してください。
b = FOREACH a GENERATE shop,sales*2
Flatten
別のデータセットをロードすると仮定します:
a = LOAD 'hdfs://localhost:9000/user/hadoop/election/health.csv' USING PigStorage(',') As (procedure, provider, name, address, city, state, zipcode, stateName, discharges, aveCharges, avePayments, aveMedicarePayments);
それはカンマ区切りのファイルを取り込み、このシンプルなタプル構造を作成しました。
describe a
a: {procedure: bytearray,provider: bytearray,name: bytearray,address: bytearray,city: bytearray,state: bytearray,zipcode: bytearray,stateName: bytearray,discharges:
bytearray,aveCharges: bytearray,avePayments: bytearray,aveMedicarePayments: bytearray}
また、明示的に定義しない場合、すべてのフィールドがbytearray型になったことにも注意してください。
今、関数を実行します。STRSPLIT関数を実行し、2つの値を生成します。ここでは、aveChargesフィールドを「$」記号(16進数24)で分割するように指示します。そのフィールドは通貨$99999の文字列です。これでは数学ができません。したがって、$記号を切り離します。STRSPLITは、左側にフィールド、右側にフィールドを持つタプルを返します。この場合、左側のフィールドは空で、$記号が最初の文字だからです。右側のフィールドは文字列の数値部分です。
b = FOREACH a GENERATE (procedure), STRSPLIT(aveCharges, '\\u0024');
今、タプルのタプルを持っており、これはバッグと呼ばれ、フィールドprocedureがあります。
dump b
((948 - SIGNS & SYMPTOMS W/O MCC,$34774.21),(,34774.21))
したがって、2番目のタプルをフラット化します:
c = FOREACH b GENERATE procedure, FLATTEN($1);
要素のこのタプルを生成し、作業を容易にします。
(948 - SIGNS & SYMPTOMS W/O MCC,,15042.00)
Filter
元のデータセットに戻ります:
(Dallas,Sam,30000)
(Dallas,Fred,40000)
(Dallas,Jane,20000)
(Houston,Jim,75000)
(Houston,Bob,65000)
New York,Earl,40000)
$40,000以上を売上げた従業員のみを選択します。
結果:
x = filter a by sales > 40000
結果:
(Houston,Jim,75000)
(Houston,Bob,65000)
結合とその他の集合操作
Pigには交差操作はありませんが、結合があります。また、union、cogroup、cross、union、その他いくつかもあります。ここでは、結合がどのように機能するかの例を示します。学生のリストと彼らが受講しているクラスのリスト、そして各クラスのコストのリストがあるとします。
students = LOAD '/root/Downloads/people.txt' USING PigStorage(',') AS (name,class);
(John,German)
(Jane,German)
(Bob,French)
class = LOAD '/root/Downloads/class.txt' USING PigStorage(',') AS (class,fee);
(German,$100)
(French,$200)
次に、両方のタプルに共通する要素で結合します。
tuition = join students by class, class by class;
(Bob,French,French,$200)
(Jane,German,German,$100)
(John,German,German,$100)
これにより、クラスとコストがすべて1つの構造に表示されます。
データ型
Pigには小さなデータ型のセットがあります。たとえば、日付データ型はありません。代わりに、float、boolean、double、bag、map、string、int、その他いくつかがあります。データ型をキャストする必要があることがよくあります。たとえば、(int) xや、型を定義する場合:x:intのように。
リレーションを保存
Pigシェルをシャットダウンすると(quitまたは[-control-][-c-]を使用します)、データセットを失います。しかし、作業を再作成できるように履歴を保存します。結果を永続的に保存するには、次のようにします:
store x into 'someName
画面に表示されるログには次のような内容が表示されます:
Successfully stored 2 records in: "file:///root/Downloads/someName"
次のように表示できます:
cat output
Houston Jim 75000
Houston Bob 65000
これをPigに再ロードすると、再びタプルになります:
(Houston,Jim,75000)
(Houston,Bob,65000)
PigはHadoopデータに対してETL(抽出、転送、ロード)操作を行うための素晴らしいツールです。PigプログラムはJavaコードよりもはるかに短いです。その基本原則は学ぶのが難しくありません。実際、シンプルさはYahooが自社の内部使用のために言語を作成した際に求めていたものです。
Hadoopガイド
- 初めてのHadoop:Hadoopの基本
- Hadoop管理の紹介
- Hadoopセキュリティの紹介
- Apache Flumeの紹介
- Hiveの紹介
- HDFSの紹介
- Hbaseの紹介
- Hadoopの例:5つの実際のユースケース
- Hadoopキャリア:雇用されるために
- Hadoop面接質問
- Hadoop分析の紹介
- Apache Pigの紹介
- Apache Yarnの紹介
- Hadoopアーキテクチャの紹介
- Hadoopの利点とメリット
- Apache CassandraとHadoopの使用
- Hadoop vs Kubernetes:K8sとクラウドネイティブはHadoopを終わらせるのか?
- Hadoop認定
- Hadoopクラスター:紹介
- Hadoopエコシステムとコンポーネント
これらの投稿は私自身のものであり、必ずしもBMCの立場、戦略、または意見を表すものではありません。