HiveからMapR-DB Binaryテーブルにアクセスする

かなり間が空いてしまいましたが、前回までにMapR-DBのBinary/Jsonテーブルについて、[データモデル](https://qiita.com/bigt23/items/e7ba51b2ed3a6bc5336a)や[maprcliコマンドからの操作](https://qiita.com/bigt23/items/2f96dc44d55c35e5f1ef)について説明しました。

今回はHiveからMapR-DB Binaryテーブルへのアクセス方法について紹介します。

前出のブログでの説明の通り、BinaryテーブルはApache HBaseとコンセプト的には同じワイドカラムストア型のデータベースとなり、HBase APIをサポートしています。
そのため、HiveからHBaseへのアクセスと基本的には[同じやり方](https://cwiki.apache.org/confluence/display/Hive/HBaseIntegration)となります。
ここではMapR 5.2 + MEP 3.0での実行例を紹介します。

まずはjar追加します。バージョンはご利用のhiveのバージョンに依存します。

```
$ hive
hive> add jar /opt/mapr/hive/hive-2.1/lib/hive-hbase-handler-2.1.1-mapr-1710.jar;
Added [/opt/mapr/hive/hive-2.1/lib/hive-hbase-handler-2.1.1-mapr-1710.jar] to class path
Added resources: [/opt/mapr/hive/hive-2.1/lib/hive-hbase-handler-2.1.1-mapr-1710.jar]
hive> add jar /opt/mapr/hbase/hbase-1.1.1/lib/hbase-client-1.1.1-mapr-1602.jar;
Added [/opt/mapr/hbase/hbase-1.1.1/lib/hbase-client-1.1.1-mapr-1602.jar] to class path
Added resources: [/opt/mapr/hbase/hbase-1.1.1/lib/hbase-client-1.1.1-mapr-1602.jar]
hive> add jar /opt/mapr/hbase/hbase-1.1.1/lib/hbase-server-1.1.1-mapr-1602.jar;
Added [/opt/mapr/hbase/hbase-1.1.1/lib/hbase-server-1.1.1-mapr-1602.jar] to class path
Added resources: [/opt/mapr/hbase/hbase-1.1.1/lib/hbase-server-1.1.1-mapr-1602.jar]
hive> add jar /opt/mapr/hbase/hbase-1.1.1/lib/hbase-protocol-1.1.1-mapr-1602.jar;
Added [/opt/mapr/hbase/hbase-1.1.1/lib/hbase-protocol-1.1.1-mapr-1602.jar] to class path
Added resources: [/opt/mapr/hbase/hbase-1.1.1/lib/hbase-protocol-1.1.1-mapr-1602.jar]
hive> add jar /opt/mapr/zookeeper/zookeeper-3.4.5/zookeeper-3.4.5-mapr-1604.jar;
Added [/opt/mapr/zookeeper/zookeeper-3.4.5/zookeeper-3.4.5-mapr-1604.jar] to class path
Added resources: [/opt/mapr/zookeeper/zookeeper-3.4.5/zookeeper-3.4.5-mapr-1604.jar]
```

つぎにテーブル作成です。
ここではSERDEPROPERTIESとして"hbase.columns.mapping"を指定する必要があります。
"hbase.columns.mapping"はHiveテーブルの各カラムとBinaryテーブルの各カラムとのマッピングを記述します。
また、オプションとしてTBLPROPERTIESに"hbase.table.name"パラメタで、Binaryテーブルのパスを指定する必要があります。
ここでは、簡単なケースとしてint型の'key'がBinaryテーブルのkeyに対応し、string型の'value'がカラムファミリー'cf1'の'val'カラムに対応するテーブルを作成します。

```
hive> create table hive_db_1(key int, value string)
    > STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
    >  WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,cf1:val")
    > TBLPROPERTIES ("hbase.table.name" = "/user/mapr/db/hive_db_1");
OK
```

テーブルが作成できましたので、データを追加してみます

```
hive> insert into table hive_db_1 values (1, '熊本');
hive> insert into table hive_db_1 values (2, '船橋');
hive> select * from hive_db_1;
OK
1       熊本
2       船橋
```

追加できました。今度はhbase shellからデータを確認してみましょう

```
$ hbase shell
1.8.7-p357 :002 > scan '/user/mapr/db/hive_db_1'
ROW                                        COLUMN+CELL
 1                                         column=cf1:val, timestamp=1519202359751, value=\xE7\x86\x8A\xE6\x9C\xAC
 2                                         column=cf1:val, timestamp=1519202359751, value=\xE8\x88\xB9\xE6\xA9\x8B
```

カラムファミリー'cf1'の'val'カラムに紐付いていることが分かります。

さて、次は既存のBinaryテーブルに対してExternal Tableを定義し、Hiveからアクセスする方法です。

まずはBinaryテーブルを作成し、適当にデータを突っ込んでみます。

```
$ hbase shell
1.8.7-p357 :014 > create '/user/mapr/db/binary_test', 'cf1'
1.8.7-p357 :014 > put '/user/mapr/db/binary_test', 'row1', 'cf1:cl1', 'val1-1'
1.8.7-p357 :014 > put '/user/mapr/db/binary_test', 'row1', 'cf1:cl2', 'val1-2'
1.8.7-p357 :014 > put '/user/mapr/db/binary_test', 'row2', 'cf1:cl1', 'val2-1'
1.8.7-p357 :014 > put '/user/mapr/db/binary_test', 'row2', 'cf1:cl2', 'val2-2'


1.8.7-p357 :014 > scan '/user/mapr/db/binary_test'
ROW                                        COLUMN+CELL
 row1                                      column=cf1:cl1, timestamp=1525016894280, value=val1-1
 row1                                      column=cf1:cl2, timestamp=1525017834326, value=val1-2
 row2                                      column=cf1:cl1, timestamp=1525016958542, value=val2-1
 row2                                      column=cf1:cl2, timestamp=1525017825056, value=val2-2
```

続いてExternal Tableを定義します。
ここでも通常のテーブルと同様、"hbase.columns.mapping"でhiveとBinaryテーブルのカラムのマッピングを、"hbase.table.name"でBinaryテーブルへのパスを指定する必要があります。
ここではBinaryテーブルのkeyとカラムファミリー'cf1'のカラム'cl1'のみを利用してExternal Tableを定義することにします。

```
$ hive
hive> create external table hive_db_external_1(key string, value string)
    > stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
    >  WITH SERDEPROPERTIES ("hbase.columns.mapping" = "cf1:cl1")
    >  TBLPROPERTIES("hbase.table.name" = "/user/mapr/db/binary_test");
OK
Time taken: 0.245 seconds
hive> select * from hive_db_external_1;
OK
row1    value1-1
row2    value2-1
```

このようにBinaryテーブルのカラムのうちから必要なカラムのみを抽出してHiveテーブルを作成できます。
一方で、より多くのカラムを抽出する場合は以下のように"hvase.columns.mapping"に抽出したいカラムを羅列します。

```
hive> create external table hive_db_external_2(key string, value string, value2 string)
     stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
      WITH SERDEPROPERTIES ("hbase.columns.mapping" = "cf1:cl1,cf1:cl2")
      TBLPROPERTIES("hbase.table.name" = "/user/mapr/db/binary_test");

hive> select * from hive_db_external_2;
OK
row1    value1-1   value1-2
row2    value2-1   value2-2
```

今回はintやstringなどシンプルな構造を持つテーブルのみを対象としました。
mapやstructを利用した例については上述のHBaseIntegrationのサンプルなどをご覧ください。