Hive on Tez を CDH で動かす

Tezとは
-----------------------
まずはTezの説明です。
TezはYARN上で動作するバッチ処理用のフレームワークで、Hortonworksが主導して開発しています。
Tezに近い位置付けのものには、リアルタイム処理用の[Slider](http://slider.incubator.apache.org/)があります。
HortonworksはSliderの上で[Storm](https://storm.apache.org/)を動かすことを[計画しています](http://hortonworks.com/blog/apache-slider-technical-preview-now-available/)。

Hive on Tezとは
-----------------------
Hive on Tezは、上記のTezの上でHiveを動かすものです。
Hive 0.13からTez対応のパッチが入っていて、動かす準備はできています。
しかし、ClouderaはCDH 5.2でHive 0.13に対応したものの、[Tezをパッケージングしませんでした](http://community.cloudera.com/t5/Cloudera-Manager-Installation/Using-Hive-on-TEZ-with-CDH5/td-p/16582)。
そのため、そのままのCDHではHive on Tezが動きません。

Hive on TezをCDHで動かす方法
-----------------------
Tezはライブラリであるため、CDHのHive 0.13と組み合わせれば動作するはずです。
どのようにCDHとTezを組み合わせたらよいでしょうか。
2つ方法があります。

1. Apacheコミュニティ版のTezを使う
1. Hortonworksのパッケージを使う

2.でも動作しますが、ClouderaとHortonworksのrpmは名前もインストール先も重複しているので、できれば避けたいところです。
ここでは「1. Apacheコミュニティ版のTezを使う」で進めます。

Tezのビルド
-----------------------
以下の手順でビルドできます。
[Hive 0.13との組み合わせにはTez 0.4が必要](http://jp.hortonworks.com/blog/introducing-apache-tez-0-4/)であることに注意してください。
Tez 0.5では「NoSuchMethodError: org.apache.tez.mapreduce.hadoop.MRHelpers.getBaseMRConfiguration」でHiveが動きません。(examplesのWordCountは動きます)
あともう1つ、libprotoc 2.5.0が必要です。
こちらもインストールしておきましょう。

ProtocolBufferのインストール
-----------------------
タグが打たれていないので、tarをダウンロードします。
make & make installでインストールします。

``` console
$ wget https://protobuf.googlecode.com/svn/rc/protobuf-2.5.0.tar.gz
$ tar xvf protobuf-2.5.0.tar.gz
$ cd protobuf-2.5.0
$ ./configure
$ make
# make install
```

必要に応じて、Linuxのライブラリとして認識させます。

``` console
# echo "/usr/local/lib" >> /etc/ld.so.conf.d/local.conf
# ldconfig
```

Tezのビルド
-----------------------
git cloneした後、タグ0.4.1を指定します。
Mavenを使用してビルドします。

``` console
$ git clone http://git.apache.org/tez.git
$ cd tez
$ git checkout -b release-0.4.1-incubating release-0.4.1-incubating
$ mvn clean package -DskipTests=true -Dmaven.javadoc.skip=true
```

Tezのインストール
-----------------------
ビルドしたTezのjarを/usr/lib/tezに配置します。

``` console
# mkdir /usr/lib/tez
# cp -r tez-dist/target/tez-0.4.1-incubating/tez-0.4.1-incubating/* /usr/lib/tez
```

TezのjarをHDFSにコピーします。

``` console
$ hadoop fs -mkdir -p /apps/tez
$ hadoop fs -put /usr/lib/tez/* /apps/tez
$ hadoop fs -chown -R hdfs:hadoop /apps/tez
$ hadoop fs -chmod -R 755 /apps
$ hadoop fs -chmod 644 /apps/tez/*.jar
$ hadoop fs -chmod 644 /apps/tez/lib/*.jar
```

Tezの設定
-----------------------
[Hortonworksのドキュメント](http://docs.hortonworks.com/HDPDocuments/HDP2/HDP-2.1-latest/bk_installing_manually_book/content/rpm-chap-tez_configure_tez.html)を参考にして、HadoopにTezの設定を行います。
hdfs:// の指定が重要なので忘れないようにしてください。

``` console
# vi /etc/tez/conf/tez-site.xml
  <configuration>
	：
    <property>
      <name>tez.lib.uris</name>
      <value>hdfs:///apps/tez/,hdfs:///apps/tez/lib/</value>
    </property>
  </configuration>
```

Tezの環境変数をサービス用の設定ファイルに追加します。

``` console
# vi /etc/default/hadoop
    ：
    export TEZ_CONF_DIR=/etc/tez/conf
    export TEZ_JARS=/usr/lib/tez/*:/usr/lib/tez/lib/*
    export HADOOP_CLASSPATH=${HADOOP_CLASSPATH}:${TEZ_CONF_DIR}:${TEZ_JARS}
```

クライアント用の設定ファイルにも同じように追加します。

``` console
# vi /etc/hadoop/conf/hadoop-env.sh
    (同上)
```

設定が完了したらHadoopクラスタを起動します。

WordCount on Tez の実行
-----------------------
動作確認を行います。
tez-mapreduce-examples-xxx.jarを指定してWordCount実行します。

``` console
$ hadoop jar /usr/lib/tez/tez-mapreduce-examples-0.4.1-incubating.jar wordcount input output
Running WordCount
：
DAG: State: SUCCEEDED Progress: 100%
VertexStatus: VertexName: tokenizer Progress: 100%
Vertex Counters for tokenizer: Counters: 24
：
DAG completed. FinalState=SUCCEEDED
```
動きましたね。

Hive on Tez の実行
-----------------------
ここまで来ればHive on Tezが動きます。
まず、テストデータを用意します。
タブ区切りで[数値\t文字列]です。

``` console
$ vi user.tsv
1	ajis_ka
2	adachij2002
3	takeuchikzm
```

HiveCLIを起動します。
データベース、テーブルを作成して、テストデータをロードします。

``` console
hive> CREATE DATABASE test_db;
hive> USE test_db;
hive> CREATE TABLE user (
        id int,
        name string)
      ROW FORMAT DELIMITED
      FIELDS TERMINATED BY '\t'
      LINES TERMINATED BY '\n';
hive> LOAD DATA LOCAL INPATH 'user.tsv' OVERWRITE INTO TABLE user;
```

実行エンジンをTezに切り替えて、クエリを実行します。

``` console
hive> SET hive.execution.engine=tez;
hive> SELECT * FROM user ORDER BY name;
Status: Running (application id: application_1417824710497_0004)
：
Status: Finished successfully
OK
2       adachij2002
1       ajis_ka
3       takeuchikzm
```

動きました！(^_^)/

追記
-----------------------
CDH 5.4以降でTezを使用した場合「NoClassDefFoundError: org/apache/hadoop/mapred/MRVersion」が発生します。[^1]
これはClouderaの独自パッチCDH-22186を適用したhadoop-mapreduce-client-common.jarが必要になるためです。
hive-site.xmlのhive.aux.jars.pathに追記することで回避できます。

``` console
# vi /etc/hive/conf/hive-site.xml
:
<property>
  <name>hive.aux.jars.path</name>
  <value>...,file:///usr/lib/hadoop-mapreduce/hadoop-mapreduce-client-common.jar</value>
</property>
```

[^1]: https://issues.apache.org/jira/browse/TEZ-3030