今回は Apache Hadoop 上で動作する MapReduce アプリケーションの一つ Apache Hive を使ってみる。 Apache Hive を使うと Hadoop/HDFS の上で HiveQL という SQL のサブセットが使えるようになる。 実行したクエリは MapReduce のジョブに変換されて Hadoop クラスタで分散並列処理されることから高スループットが得られる。
ただし、MapReduce アプリケーションのご多分に漏れずレイテンシーはでかい。 ようするに一つ一つのクエリの実行自体には時間がかかってしまう。 また、一度追加したレコードについては基本的に更新したり削除することができない。 それらの特性から、オンライントランザクション処理 (OLTP) のような用途には全く向いていない。 代わりに、どんどん一方的にデータが蓄積されていくような状況で後からバッチとかで集計するような用途には向いていると思う。
そんな Apache Hive を今回は CentOS7 上に構築して使ってみる。 今回も Hadoop ディストリビューションは使わず、OSS のリリースパッケージをそのままインストールする。 その方が、おそらく挙動や設定について多くの知見が得られると思うので。 そして、Apache Hive は Apache Hadoop/HDFS 上で動作する。 そのため、今回使う環境は以下のエントリにもとづいて Apache Hadoop が疑似分散モードでセットアップ済みなことを想定する。
上記のエントリにもあるけど、今回使った環境は次の通り。
$ cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core) $ uname -r 3.10.0-514.16.1.el7.x86_64 $ bin/hadoop version Hadoop 2.8.0 Subversion https://git-wip-us.apache.org/repos/asf/hadoop.git -r 91f2b7a13d1e97be65db92ddabc627cc29ac0009 Compiled by jdu on 2017-03-17T04:12Z Compiled with protoc 2.5.0 From source with checksum 60125541c2b3e266cbf3becc5bda666 This command was run using /home/vagrant/hadoop-2.8.0/share/hadoop/common/hadoop-common-2.8.0.jar
インストールする
インストール方法については次のドキュメントを参照した。 ただし、Apache Hive 2.x 系についてはここに書かれている内容だけではエラーになってしまった。 そのため公式サイト以外にも調べて必要な手順を足している。
GettingStarted - Apache Hive - Apache Software Foundation
AdminManual Installation - Apache Hive - Apache Software Foundation
下準備
まずはパッケージをダウンロードするために wget
をインストールしておく。
$ sudo yum -y install wget
続いては環境変数 HADOOP_HOME
に Apache Hadoop のインストール先ディレクトリを指定しておく。
$ export HADOOP_HOME=~/hadoop-2.8.0
続いては Apache Hive のパッケージをダウンロードする。 ミラーサイトは次の通りなので、好きなところを選ぼう。
ただし、現状で Apache Hive には 1.x 系と 2.x 系という二つのメジャーバージョンが併用されている。 軽く調べた感じ、まだ 1.x 系の方が使われているっぽいかな? ただ、2.x 系には 1.x 系にない機能が色々とあるみたい。 ちなみに、どうやら Apache Hive は最新の安定版リリース以外ダウンロードサイトに置いていないようだ。
バージョン 1.x を使う場合
もしバージョン 1.x 系を使うときは、こうする。
$ wget http://ftp.riken.jp/net/apache/hive/hive-1.2.2/apache-hive-1.2.2-bin.tar.gz $ tar xf apache-hive-1.2.2-bin.tar.gz $ cd apache-hive-1.2.2-bin
バージョン 2.x を使う場合
バージョン 2.x 系を使うときは、こう。
$ wget http://ftp.riken.jp/net/apache/hive/hive-2.1.1/apache-hive-2.1.1-bin.tar.gz $ tar xf apache-hive-2.1.1-bin.tar.gz $ cd apache-hive-2.1.1-bin
セットアップする
どちらのメジャーバージョンを使うときも同じ手順でセットアップできるようだ。 ただし 2.x 系については 1.x 系で不要な操作も必ずしなければいけないようになっている。
まずは HDFS に Hive のデータ置き場を作る。
$ $HADOOP_HOME/bin/hadoop fs -mkdir -p /user/hive/warehouse $ $HADOOP_HOME/bin/hadoop fs -chmod g+w /user/hive/warehouse
同様にテンポラリディレクトリも必要なので作っておこう。
$ $HADOOP_HOME/bin/hadoop fs -mkdir -p /tmp $ $HADOOP_HOME/bin/hadoop fs -chmod g+w /tmp
続いては Apache Hive がメタデータを入れておく RDBMS を準備する。 これには MySQL とか PostgreSQL とかも使えるけど、デフォルトでは Apache Derby という Java で書かれた組み込みのものが使われる。
$ bin/schematool -dbType derby -initSchema --verbose ...(snip)... Initialization script completed schemaTool completed
これで下準備はおわり。
使ってみる
続いては、実際に Apache Hive を使ってみることにしよう。
それにはまず hive
というコマンドを起動する。
$ bin/hive
すると、次のように HiveQL を入力するためのシェルが起動する。
hive>
ちなみに、このとき 2.x 系を使っていると次のような警告が出る。 どうやら 2.x 系では MapReduce で動作させるのは非推奨となっていて、代わりに Spark とか Tez の上で動かせってことらしい。 ここらへんはまだよく分かっていないけど、おそらくレイテンシーの大きさを改善するための試みな気がしている。
Hive-on-MR is deprecated in Hive 2 and may not be available in the future versions. Consider using a different execution engine (i.e. spark, tez) or using Hive 1.X releases.
シェルの使い方
基本的には MySQL なんかのシェルを使うのと似たような感じで操作できる。
例えばデータベースの一覧を得るには SHOW DATABASES
コマンドが使える。
hive> SHOW DATABASES; OK default Time taken: 0.011 seconds, Fetched: 1 row(s)
今操作しているデータベースを表示したいときは、こうする。
hive> set hive.cli.print.current.db=true;
シェルの中に表示されるようになった。
hive (default)>
データベースを作る
データベースを新しく作るには CREATE DATABASE
コマンドを使う。
hive (default)> CREATE DATABASE mydb; OK Time taken: 0.106 seconds
使うには USE
コマンドを。
ここらへんは MySQL とほとんど同じ。
hive (default)> USE mydb; OK Time taken: 0.038 seconds hive (mydb)>
テーブルを作る
続いてはテーブルを作ってみる。 ここも至って普通の SQL が使える。 代理キーを入れてみたけど、特に自動生成してくれるような機能はなさそうかな・・・?
hive (mydb)> CREATE TABLE users ( > id INT, > name STRING, > age INT > ); OK Time taken: 0.068 seconds
SHOW TABLES
で確認すると、ちゃんとテーブルができている。
hive (mydb)> SHOW TABLES; OK users Time taken: 0.022 seconds, Fetched: 1 row(s)
続いてはレコードを追加してみる。 さっきまでの処理は単に RDB にメタデータを追加するだけで済んでいたのかすぐに終わったけど、この処理には結構かかる。 がっつり MapReduce のジョブに変換されているみたいだ。
hive (mydb)> INSERT INTO users VALUES (1, 'Alice', 20); ...(snip)... Total MapReduce CPU Time Spent: 1 seconds 860 msec OK Time taken: 31.601 seconds
SELECT
で追加されたレコードを確認してみよう。
hive (mydb)> SELECT * FROM users; OK 1 Alice 20 Time taken: 0.22 seconds, Fetched: 1 row(s)
ちなみに、クエリがどう処理されているかを詳しく見るには EXPLAIN
を先頭につけるらしい。
hive (mydb)> EXPLAIN SELECT * FROM users; OK STAGE DEPENDENCIES: Stage-0 is a root stage STAGE PLANS: Stage: Stage-0 Fetch Operator limit: -1 Processor Tree: TableScan alias: users Statistics: Num rows: 1 Data size: 10 Basic stats: COMPLETE Column stats: NONE Select Operator expressions: id (type: int), name (type: string), age (type: int) outputColumnNames: _col0, _col1, _col2 Statistics: Num rows: 1 Data size: 10 Basic stats: COMPLETE Column stats: NONE ListSink Time taken: 0.086 seconds, Fetched: 17 row(s)
続いては複数のテーブルを連結してみる。 試しにユーザのメールアドレスを想定したテーブルを作ってみよう。
hive (mydb)> CREATE TABLE emails ( > id INT, > address STRING > ); OK Time taken: 0.062 seconds hive (mydb)> INSERT INTO emails VALUES (1, 'alice@example.jp'); ...(snip)... OK Time taken: 18.881 seconds
テーブル同士を連結 (JOIN) するときも一般的な RDBMS と同じようにできる。 ただし、この処理も実行には時間がかかる。
hive (mydb)> SELECT * > FROM users > JOIN emails ON users.id = emails.id > WHERE name like 'Alice'; ...(snip)... OK 1 Alice 20 1 alice@example.jp Time taken: 31.934 seconds, Fetched: 1 row(s)
ところで、これまで見てきたテーブルなどのデータは HDFS 上にどのようにして格納されているのだろう? 見ると、次のようにテーブルごとでディレクトリになってその中にファイルが入っている。
$ $HADOOP_HOME/bin/hdfs dfs -ls -R /user/hive/warehouse drwxrwxr-x - vagrant supergroup 0 2017-05-22 21:35 /user/hive/warehouse/mydb.db drwxrwxr-x - vagrant supergroup 0 2017-05-22 21:35 /user/hive/warehouse/mydb.db/emails -rwxrwxr-x 1 vagrant supergroup 19 2017-05-22 21:35 /user/hive/warehouse/mydb.db/emails/000000_0 drwxrwxr-x - vagrant supergroup 0 2017-05-22 21:33 /user/hive/warehouse/mydb.db/users -rwxrwxr-x 1 vagrant supergroup 11 2017-05-22 21:33 /user/hive/warehouse/mydb.db/users/000000_0
さらにファイルの中身を見てみると・・・なんと、ただのテキストファイルになっている。 こんなデータ構造でも上手くいくのは Hadoop クラスタと HDFS の賜物といえるだろう。 HDFS で各ノードに分散配置された細切れのファイルを Hadoop クラスタが分散並列実行するために高いスループットが得られる。
$ $HADOOP_HOME/bin/hdfs dfs -cat /user/hive/warehouse/users/000000_0
1Alice20
テーブルを削除するには DROP TABLE
を使う。
hive (mydb)> DROP TABLE users; OK Time taken: 0.946 seconds hive (mydb)> DROP TABLE emails; OK Time taken: 0.113 seconds
テーブルを削除すればディレクトリごとファイルもなくなる。
$ $HADOOP_HOME/bin/hdfs dfs -ls -R /user/hive/warehouse drwxrwxr-x - vagrant supergroup 0 2017-05-22 12:39 /user/hive/warehouse/mydb.db
データ構造を CSV にする
先ほど見た通り Apache Hive が扱うデータ構造は、デフォルトではただのテキストファイルになっている。 このことから、データ構造を例えば CSV にすることもできる。
テーブルを作るときのオプションとしてカンマ区切りになるよう指定しよう。
hive (mydb)> CREATE TABLE users ( > id INT, > name STRING, > age INT > ) > ROW FORMAT DELIMITED > FIELDS TERMINATED BY ',' > STORED AS TEXTFILE; OK Time taken: 0.079 seconds
もちろん、こうしておけば外部から CSV を読み込むこともできる。 例えば、次のようなファイルを用意しよう。
$ cat << 'EOF' > /tmp/users.csv 1,Alice,20 2,Bob,30 3,Carol,10 EOF
そして Hive で LOAD DATA
を使って、それを読み込む。
hive (mydb)> LOAD DATA LOCAL INPATH '/tmp/users.csv' INTO TABLE users; Loading data to table mydb.users Table mydb.users stats: [numFiles=1, totalSize=31] OK Time taken: 0.223 seconds
データがちゃんと読み込まれている。
hive (mydb)> SELECT * FROM users WHERE age < 25; OK 1 Alice 20 3 Carol 10 Time taken: 0.141 seconds, Fetched: 2 row(s)
そして、HDFS 上のデータの中身もこの通り。
$ $HADOOP_HOME/bin/hdfs dfs -ls -R /user/hive/warehouse | grep users.csv -rwxrwxr-x 1 vagrant supergroup 31 2017-05-22 21:40 /user/hive/warehouse/mydb.db/users/users.csv $ $HADOOP_HOME/bin/hdfs dfs -cat /user/hive/warehouse/mydb.db/users/users.csv 1,Alice,20 2,Bob,30 3,Carol,10
Vagrantfile
上記のセットアップを手動でやるのは大変なので Vagrant で自動化してみた。 使い方は次の通り。
$ git clone https://gist.github.com/d89890c1e9874f5e15f8cff9311544a5.git hadoop-cluster-with-hive $ cd hadoop-cluster-with-hive $ sh boot.sh
あとはマスターノードにログインして色々とやる。
$ vagrant ssh master
まとめ
今回は CentOS7 に Apache Hive をインストールして使ってみた。 Apache Hive を使うことで Hadoop/HDFS 上でスケーラブルなデータストアを構築できる。 構築したデータストアは HiveQL という SQL のサブセットを通して操作できる。 HiveQL は、実行されると MapReduce のジョブに変換された上で Hadoop クラスタ上で並列分散実行される。 そのためレイテンシーは大きいものの高いスループットが期待できるようだ。
今回も次の本が理解の役に立った。
Hadoop徹底入門 第2版 オープンソース分散処理環境の構築
- 作者: 太田一樹,岩崎正剛,猿田浩輔,下垣徹,藤井達朗,山下真一,濱野賢一朗
- 出版社/メーカー: 翔泳社
- 発売日: 2013/07/09
- メディア: 大型本
- この商品を含むブログ (5件) を見る