Mac上にhadoop/hiveを入れて、 S3上のファイルをhiveでアクセスするまでの手順のメモを残しておきます。

  • Hadoopとhiveのセットアップ
  • S3上のファイルへのアクセス設定
  • S3上のTSVファイルへのクエリ実行
  • S3上にクエリの実行結果を保存

Hadoopとhiveのセットアップ

homebrewを使ってhadoopとhiveのインストール、 その後必要となる設定を行います。

インストール

jdk及びhomebrewはセットアップ済みとして、
以下のコマンドでhadoopとhiveをインストールします。

$ brew install hadoop
$ brew install hive

以下のコマンドで、インストール出来たことを確認します。

$ hadoop version
$ hive -H

HADOOP_HOMEの設定

環境変数「HADOOP_HOME」「HADOOP_CONF_DIR」を設定しておきます。

hadoop versionの出力結果を見て、以下のように設定します。
以下は私の環境の場合の設定です。

$ hadoop version
Hadoop 2.7.2
※省略※
This command was run using /usr/local/Cellar/hadoop/2.7.2/libexec/share/hadoop/common/hadoop-common-2.7.2.jar
$ echo 'export HADOOP_HOME=/usr/local/Cellar/hadoop/2.7.2' >> ~/.bash_profile
$ echo 'export HADOOP_CONF_DIR=$HADOOP_HOME/libexec/etc/hadoop' >> ~/.bash_profile
$ . ~/.bash_profile

localhostへのssh接続設定

localhostにsshで接続できるように設定します。

システム環境設定 → 共有 から、「リモートログイン」にチェックを入れます。

以下のコマンドでauthorized_keysを追加します。
※まだ公開鍵を作成していない場合はssh-keygenで作成します。

$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys

以下のコマンドでlocalhostにsshで接続できることを確認します。

$ ssh localhost

HDFS設定とnamenodeの起動

次に、疑似分散モードでHDFSを構成します。

参考: Hadoop: Setting up a Single Node Cluster.
https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/SingleCluster.html

core-site.xml/hdfs-site.xmlを以下のように変更します。

$HADOOP_CONF_DIR/core-site.xml

<configuration>
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://localhost:9000</value>
    </property>
</configuration>

$HADOOP_CONF_DIR/hdfs-site.xml

<configuration>
    <property>
        <name>dfs.replication</name>
        <value>1</value>
    </property>
</configuration>

以下のコマンドでnamenodeを初期化します。

$ hadoop namenode -format

以下のコマンドでHDFSを起動します。
※停止する場合は $HADOOP_HOME/sbin/stop-dfs.sh

$ $HADOOP_HOME/sbin/start-dfs.sh

以下のコマンドでHDFSを参照できることを確認します。
※まだHDFS上にファイルが無いので一覧には何も表示されません。

$ hadoop fs -ls /

S3上のファイルへのアクセス設定

Mac上のhadoopからS3にアクセスできるように設定を行います。

awsのjarにパスを通す

S3AFileSystemを使えるようにするため、
「hadoop-aws-2.7.2.jar」にCLASSPATHを通します。
hadoop-env.shに以下を追記します。

$HADOOP_CONF_DIR/hadoop-env.sh

export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:$HADOOP_HOME/libexec/share/hadoop/tools/lib/*

S3AFileSystemとアクセスキーを設定

「yarn-site.xml」を以下のように編集し、hadoopがS3にアクセス出来るようにします。

$HADOOP_CONF_DIR/yarn-site.xml

<?xml version="1.0"?>
<configuration>
  <property>
    <name>fs.s3a.impl</name>
    <value>org.apache.hadoop.fs.s3a.S3AFileSystem</value>
  </property>
  <property>
    <name>fs.s3a.access.key</name>
    <value>※ここにAWSのアクセスキー※</value>
  </property>
  <property>
    <name>fs.s3a.secret.key</name>
    <value>※ここにAWSのシークレットキー※</value>
  </property>
</configuration>

S3へのアクセス確認

hadoopコマンドでS3のbucketにアクセスできることを確認します。

$ hadoop fs -ls s3a://※ここにS3のbucket名※/

S3上のTSVファイルへのクエリ実行

次に、S3上に配置したTSVファイルに対してhiveでクエリを投げてみます。

hiveの起動

以下のコマンドでhiveを起動します。

$ hive

S3上のtsvファイルへのアクセス

とりあえず、以下のように「日時」「支店」「金額」がタブ区切りで入力された、
店舗別の売り上げデータがあるとします。

2012-11-20 10:35:00  東京店 1000
2012-12-05 19:07:00  大阪店 1200
2012-12-07 12:42:00  京都店 2200
2012-12-10 13:05:00  東京店 1800

このファイルをS3 bucketの以下のパスに配置します。
 /hive/external/sales/sales001

次のように、配置したtsvファイルを外部テーブルとして定義します。

hive> create external table sales (
saletime timestamp,
shop string,
amount int
)
row format delimited
fields terminated by '\t' lines terminated by '\n'
stored as textfile location 's3a://※ここにS3のbucket名※/hive/external/sales';

テーブルを定義できたら、 hiveで該当のテーブルにクエリを投げることができます。
例えば、次のようにして店舗別の売り上げ集計を行うことができます。

hive> select shop, sum(amount) from sales group by shop;
京都店	2200
大阪店	1200
東京店	2800

S3上にクエリの実行結果を保存

ここまででクエリを実行できたので、今度はクエリの実行結果をS3上に保存してみます。

出力先テーブルの作成

次のようにして、出力先のテーブルを作成します。

hive> create external table sales_by_shop(shop string, amount int)
partitioned by (ym string)
stored as textfile location 's3a://※ここにS3のbucket名※/hive/external/sales_by_shop';

クエリの実行と登録

以下のクエリを実行して、実行結果を先ほど作成したテーブルに保存します。

hive> alter table sales_by_shop add partition (ym=201211);
hive> insert into sales_by_shop partition(ym=201211)
select shop, sum(amount) from sales where saletime between '2012-11-01' and '2012-11-30' group by shop;
hive> alter table sales_by_shop add partition (ym=201212);
hive> insert into sales_by_shop partition(ym=201212)
select shop, sum(amount) from sales where saletime between '2012-12-01' and '2012-12-31' group by shop;

保存されたデータの確認

クエリの実行後、以下のコマンドでpartitionができていることを確認できます。

$ hadoo fs -ls s3a://※ここにS3のbucket名※/hive/external/sales_by_shop
drwxrwxrwx   -          0 1970-01-01 09:00 s3a://※ここにS3のbucket名※/hive/external/sales_by_shop/ym=201211
drwxrwxrwx   -          0 1970-01-01 09:00 s3a://※ここにS3のbucket名※/hive/external/sales_by_shop/ym=201212

また、以下のようにすると、保存されたファイルの中身を確認できます。

$ hadoop fs -cat s3a://※ここにS3のbucket名※/hive/external/sales_by_shop/ym=201212/*
京都店2200
大阪店1200
東京店1800

以上で、Mac上のhiveからS3のファイルにアクセスできるようになりました。

S3を使う場合は、EC2やEMR上のhadoopから処理をした方が(ネットワーク的に)有利ですが、
手元で環境変更したり、UDFを開発したりなどの用途で、
このようにMac上のhadoopからS3にアクセスできると便利かもしれないです。