とりあえずPig on Tez を動かしてみた

9月9日のHadoopソースコードリーディングに参加してTezの現状を知ることができました。 折角のタイミングということで、Pig on Tezを動かしてみようと思いました。

PigのTez対応は次のバージョンである0.14からですが、まだリリースされていません。そのため、Tezのコードが含まれるtrunkビルドしたものを利用したいと思います。

最初に結論 : Pig on Tezは良い!

利用した環境

今回 Pig on Tezは、YARN擬似分散環境を構築しました。 それぞれのバージョンは以下の通りです。

  • Hadoop : 3.0.0-SNAPSHOT (9/12にtrunkをビルドしたもの)
  • Pig : 0.14.0-SNAPSHOT (9/12にtrunkをビルドしたもの)
  • Tez : 0.6.0-SNAPSHOT (9/12にtrunkをビルドしたもの)

Pigは、ビルドする際に"-Dhadoopversion=23"を付与することで、Hadoop2系用JARファイルが生成されます。未だに、23を指定しなければならないのですね。

Tezは、tez-distディレクトリ以下にtarballが生成されています。これを利用します。

Pig on Tez を利用するための準備

それぞれtrunkをビルドしたものの、それだけではMapReduce版のPigが動いてしまいますので、Tezで動作させるように設定します。

Hadoopの設定

とりあえず、YARN環境を構築しましょう。そして、Tezを利用するための設定として、mapred-site.xmlに以下の項目を競ってします。

  • プロパティ名 : mapreduce.framework.name
  • 値 : yarn-tez

YARN上でのMapReduceではyarnと設定しますが、Tezを使うのでyarn-tezを指定します。

Tezライブラリの配置

YARN上でのTezを動作させるために、TezライブラリをHDFS上に配置します。Tezプロジェクトに記載されているような形です。http://tez.apache.org/install.html

今回は、先にビルドしたTezライブラリを以下のようにHDFS上に配置しました。

[root@hadoop ~]# hdfs dfs -put /tmp/tez-0.6.0-SNAPSHOT.tar.gz /tez/
[root@hadoop ~]# hdfs dfs -ls /tez
Found 1 items
-rw-r--r--   3 root supergroup   33794017 2014-09-11 20:32 /tez/tez-0.6.0-SNAPSHOT.tar.gz

このTezライブラリは、Pig起動時にset文で、"tez.lib.uris"プロパティの値としてHDFSのパスを指定します。以下のような形でGruntシェルで指定します(もちろん、設定ファイルに定義しても構いません。)

grunt> set tez.lib.uris hdfs://hadoop:8020/tez/tez-0.6.0-SNAPSHOT.tar.gz

なお、異なるバージョンのTezライブラリをHDFSに格納して実行時に指定することができる点は、Tezのポイントです。

サンプルデータ

以下の2つを用意しました。

[root@hadoop ~]# cat airport.txt
1,nrt
2,hnd
3,kix
4,itm
5,IZO

と、

[root@hadoop ~]# cat flight.txt
NH23,2,4,777-200
JL117,2,4,777-200
NH25,2,4,787-8
JL119,2,4,767-300
NH27,2,4,777-200
JL121,2,4,767-200
NH31,2,4,767-300
JL125,2,4,777-200
NH33,2,4,777-200
JL127,2,4,777-200
7G23,2,3,320
7G25,2,3,320
GK207,1,3,320
AP116,1,3,320
JL3005,1,4,737-800
JL1667,2,5,767-300
JL1669,2,5,737-800

このファイルをHDFS上に格納します。

サンプルコード

今回、サンプルデータを加工するPig構文を用意します。2つのデータを結合したり、集約することをあえて意識しています。

FLIGHT = LOAD 'flight.txt' USING PigStorage(',') AS (number:chararray, from:int, to:int, equip:chararray);
AIRPORT = LOAD 'airport.txt' USING PigStorage(',') AS (id:int, name:chararray);
FILTER_FLIGHT = FILTER FLIGHT BY equip != '777-300';
FLIGHT_DATA = FOREACH FILTER_FLIGHT GENERATE SUBSTRING(number, 0, 2), number, from, to;
JOIN_DATA = JOIN FLIGHT_DATA BY from, AIRPORT BY id;
FLIGHT_DATA2 = FOREACH JOIN_DATA GENERATE $0, number, AIRPORT::name;
GROUP_DATA = GROUP FLIGHT_DATA2 BY (AIRPORT::name, $0);
COUNT_DATA = FOREACH GROUP_DATA GENERATE group, COUNT(FLIGHT_DATA2);
DUMP COUNT_DATA;

Pig on Tezの実行

Tezを利用する場合は、Pigコマンドの引数で"-x tez"を指定します。なお、"-x tez_local" でローカル上でTezにてPigを処理させるモードもあります。MapReduceの場合も"local"モードがありました。

[root@hadoop ~]# /usr/local/pig/bin/pig -x tez
14/09/12 05:55:30 INFO pig.ExecTypeProvider: Trying ExecType : LOCAL
14/09/12 05:55:30 INFO pig.ExecTypeProvider: Trying ExecType : MAPREDUCE
14/09/12 05:55:30 INFO pig.ExecTypeProvider: Trying ExecType : TEZ_LOCAL
14/09/12 05:55:30 INFO pig.ExecTypeProvider: Trying ExecType : TEZ
14/09/12 05:55:30 INFO pig.ExecTypeProvider: Picked TEZ as the ExecType
grunt>

ExecTypeでTezが設定されました。先に定義したサンプルコードを実行してみました。

2014-09-12 06:30:59,056 [main] INFO  org.apache.pig.tools.pigstats.tez.TezStats - Script Statistics:

     HadoopVersion: 3.0.0-SNAPSHOT
        PigVersion: 0.14.0-SNAPSHOT
        TezVersion: 0.5.0
            UserId: root
          FileName:
         StartedAt: 2014-09-12 06:30:45
        FinishedAt: 2014-09-12 06:30:59
          Features: HASH_JOIN,GROUP_BY,FILTER

Success!

     ApplicationId: application_1410486427098_0012
TotalLaunchedTasks: 4
     FileBytesRead: 1248
  FileBytesWritten: 2106
     HdfsBytesRead: 314
  HdfsBytesWritten: 105

Input(s):
Successfully read 17 records (284 bytes) from: "hdfs://hadoop:8020/user/root/flight.txt"
Successfully read 5 records (30 bytes) from: "hdfs://hadoop:8020/user/root/airport.txt"

Output(s):
Successfully stored 6 records (105 bytes) in: "hdfs://hadoop:8020/tmp/temp903517041/tmp403811983"

2014-09-12 06:30:59,070 [main] INFO  org.apache.hadoop.mapreduce.lib.input.FileInputFormat - Total input paths to process : 1
2014-09-12 06:30:59,070 [main] INFO  org.apache.pig.backend.hadoop.executionengine.util.MapRedUtil - Total input paths to process : 1
((hnd,7G),2)
((hnd,JL),7)
((hnd,NH),5)
((nrt,AP),1)
((nrt,GK),1)

無事、Pig on Tezでコードを実行することができました。JOINやGROUPが含まれるMapReduceジョブの場合、複数のジョブが実行されるため処理時間は結構長くなるのですが、Tezの場合15秒で完了することができました。

(MapReduceモードでも実行したのですが、40秒弱と倍程度時間がかかりました。特に2回ApplicationMasterを起動する必要があったため、その時間も影響を受けていました。)

おまけ

TezでPig Latinを実行した後、ResourceManagerのWebインタフェースを見ると、TezのApplicationMasterが起動しっぱなしであることに気が付きました。

f:id:sinchii:20140912225155p:plain

これは、TezのSession機能によるものです。何度もApplicationMasterを起動することなく1つのApplicationMasterを利用することで、処理時間を短縮させることができます。 quitでgruntシェルを終了するとSessionも終了しApplicationMasterも完了します。(詳しい仕組みは追々...)

おわりに

PigでもTezを利用して、YARN上で動作させることができました。とりあえず動かしてみて感じたPig on Tezの嬉しい点は、MRv1時に利用していたPig Latinがそのまま利用できることPig Latinをより厳密に実行できるので性能改善できることでしょうか。

新たにコードを書く必要なく、そのまま利用出来る点は非常に魅力的です。移行時の手間が省けるのは、本当に有用です。 とは言え、UDFの利用とか未確認のものがあるので、その辺りは追々調べます。

現在のHadoop 2系は、MapReduceを実行するのであれば、そこそこ動作する印象はあります。一方、Tezも強力なパーツであると思います。Pig on Tezが利用できる 0.14 系のリリースが楽しみです!

(Pig on Tezは動作した。Apache Flinkはとりあえず優先度を落とすということで。。。)