wiki:PigGrunt

Version 2 (modified by kosuke, 10 years ago) (diff)

--

Gruntを使ってみる

作者:kosuke

参考文献:Tom White(2009/6/16) Hadoop: The Definitive Guide O'REILLY 501pp

以下に書くのは、Gruntを使ってPigを動かした簡単な例です。

例えば、年、温度、データの信頼性、の三つの要素が書かれているテキストファイルの最高温度とその年を解析して表示させるコマンドを紹介する。

1.テキストファイルを生成する。

年、温度(測定不能の場合は9999にする)、データの信頼性(0,1,4,5,9の5段階で評価されている)の三つの要素がtabで区切られているテキストファイルを作る。例えば以下のようにすればよい。temperature.txtで保存する.

1990  34  1
1432  32  9999
1345  24  2
1945  11  3
1987  12  5
1765  13  9
1254  22  1
1123  14  9999
1945  13  4
1432  23  5
1990  12  9

2.Pig実行

pig-0.4.0のディレクトリに移動してbinディレクトリのpigを実行する(ローカルの場合).

cd pig-0.4.0

bin/pig -x local

3.テキストファイルをタプル形式に変換する。

テキストファイルをタプル形式に変換する場合は、LOADオペレータを使う。その際、書く要素に名前を定義する。以下のコマンドを実行する.

grunt>records = LOAD '1.のテキストが保存されたディレクトリ/temperature.txt' AS (year:chararray,temperature:int,quality:int);

何も表示されなければ成功。LOADは、テキストファイルに書かれた年、温度、信頼性の要素を取り出し、タプルの形に変更してくれる。注意:SQLの様にLOADやASは小文字でも構わない.

4.recordsの中身を表示してみる。

recordsのようなものを、表示させたいときはDUMPコマンドを利用する。

grunt>DUMP records;

以下のような結果が表示されれば成功。たぶんDUMPを実行した時にはじめて処理が実行されるんだと思う。

(1990,34,1)
(1432,32,9999)
(1345,24,2)
(1945,11,3)
(1987,12,5)
(1765,13,9)
(1254,22,1)
(1123,14,9999)
(1945,13,4)
(1432,23,5)
(1990,12,9)

5.各要素がどういう名前で定義されているのか見る

DESCRIBEコマンドを使う。

grunt>DESCRIBE records;

以下の用に表示されれば成功。

 records: {year: chararray,temperature: int,quality: int}

6.間違っている要素が含まれるデータを排除する。

FILTERを使うとBY以下の条件に引っかかるものだけが取り出される.

filtered_records = FILTER records BY quality == 0 OR quality ==1 OR quality == 2 OR quality == 3 OR quality == 4 OR quality == 5 OR quality == 9;

4.のように表示させて確かめる.

grunt>DUMP filtered_records;

以下の用に表示されれば成功である.

(1990,34,1)
(1345,24,2)
(1945,11,3)
(1987,12,5)
(1765,13,9)
(1254,22,1)

7.同じ年のデータをグループ化する。

グループ化したいときは、GROUPを使う.

grunt>grouped_records = group filtered_records by year;

4.の用に表示させて確かめる。

(1254,{(1254,22,1)})
(1345,{(1345,24,2)})
(1432,{(1432,23,5)})
(1765,{(1765,13,9)})
(1945,{(1945,11,3),(1945,13,4)})
(1987,{(1987,12,5)})
(1990,{(1990,34,1),(1990,12,9)})

この様に表示されれば成功。また、グループ化されたリストがどういう名前で定義されているか確かめる。5.のようにDESCRIBEを使う。

grunt>DESCRIBE grouped_records;

以下のように表示されるべきである。

grunt>grouped_records: {group: chararray,filtered_records: {year: chararray,temparture: int,quality: int}}

この通り、groupという名前のchararray(javaで言うstring)が最初の要素で,二つ目の要素が6で作ったfiltered_recordsになっています.

8.各年の温度の最大値を求める。

それぞれのタプルについて処理する場合はFOREACHを使います.また、新たなタプルを作る場合(この場合は、(年,その年の温度の最高値))は、GENERATEを使います.

grunt>max_temp = FOREACH grouped_records generate group,MAX(filtered_records.temperature);

groupはgrouped_recordsのgroup、filtered_records.temperatureはfiltered_recordsのtempartureを指し示しています.MAXは、指し示した要素の中での最高値をかえす.

表示して確かめる。

DUMP max_temp;

以下の用に表示されれば成功です。

(1254,22)
(1345,24)
(1432,23)
(1765,13)
(1945,13)
(1987,12)
(1990,34)

9.補足:もっと高級に表示させる。

DUMPではただのタプルが表示されているだけで、どの要素がどういう名前を持っているのか一目でわかりません。また、どれとどれがリレーションしているのかもわかりません。こういったことが一目でわかりやすく表示させるためにはILLUSTRATEコマンドを使うことが有効です.

grunt>ILLUSTRATE max_temp;

-------------------------------------------------------------------------------
| records     | year: bytearray | temperature: bytearray | quality: bytearray |
-------------------------------------------------------------------------------
|             | 1945            | 11                     | 3                  |
|             | 1765            | 13                     | 9                  |
|             | 1123            | 14                     | 9999               |
|             | 1945            | 13                     | 4                  |
-------------------------------------------------------------------------------
-------------------------------------------------------------------
| records     | year: chararray | temperature: int | quality: int |
-------------------------------------------------------------------
|             | 1945            | 11               | 3            |
|             | 1765            | 13               | 9            |
|             | 1123            | 14               | 9999         |
|             | 1945            | 13               | 4            |
-------------------------------------------------------------------
----------------------------------------------------------------------------
| filtered_records     | year: chararray | temperature: int | quality: int |
----------------------------------------------------------------------------
|                      | 1945            | 11               | 3            |
|                      | 1765            | 13               | 9            |
|                      | 1945            | 13               | 4            |
----------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------
| grouped_records     | group: chararray | filtered_records: bag({year: chararray,temperature: int,quality: int}) |
-------------------------------------------------------------------------------------------------------------------
|                     | 1765             | {(1765, 13, 9)}                                                        |
|                     | 1945             | {(1945, 11, 3), (1945, 13, 4)}                                         |
-------------------------------------------------------------------------------------------------------------------
-------------------------------------------
| max_temp     | group: chararray | int   |
-------------------------------------------
|              | 1765             | 13    |
|              | 1945             | 13    |
-------------------------------------------

この様に表示れれば成功です。

10.hadoopモード(シングルノード)とローカルモードの比較

前述のhadoop vs python でも述べたが、シングルノードのhadoopは圧倒的におそい。ローカルモードは下記の処理を約1msで実行終了しているのに対し、hadoopモードは、約8.3sもの時間がかかる。