JSON
drill
Binary
MapR
MapR-DB
MapRDay 10

DrillからMapR-DBにアクセスする

今回はDrillからMapR-DBにアクセスする方法について紹介します。
とは言ってもMapR-DBへの接続はdfsプラグインを使うだけ、と非常に簡単で、MapRのドキュメントサイトでも多く触れられていますので、今回の記事はメモ程度の扱いになるかと思います。
英語でオーケーな方はこちらからどうぞ

Binary テーブル

まずはテーブルを作成します。
今回はColumnFamily cf1, cf2を持ち、それぞれにいくつかのカラムを持つテーブルを想定します。

$ hadoop fs -cat /tmp/file1.txt
row0,cf2val0,0,cf1val0,10
row1,cf2val1,1,cf1val1,11
row2,cf2val2,2,cf1val2,12
row3,cf2val3,3,cf1val3,13
row4,cf2val4,4,cf1val4,14
row5,cf2val5,5,cf1val5,15
row6,cf2val6,6,cf1val6,16
row7,cf2val7,7,cf1val7,17
row8,cf2val8,8,cf1val8,18
row9,cf2val9,9,cf1val9,19

$ hbase shell

hbase(main):002:0* create '/user/mapr/db/binary_table_1', {NAME => 'cf1'}, {NAME => 'cf2'}
0 row(s) in 0.1650 seconds


$ hadoop jar /opt/mapr/hbase/hbase-1.1.8/lib/hbase-server-1.1.8-mapr-1710.jar \
             importtsv -Dimporttsv.separator=, \ 
             -Dimporttsv.columns=HBASE_ROW_KEY,cf2:c1,cf1:c2,cf1:c1,cf2:c2 \
             '/user/mapr/db/binary_table_1' /tmp/file1.txt

続いてBinaryテーブルにクエリを実行してみます。
MapR-DBへのクエリはdfsプラグインでテーブルへのパスを指定するだけです。
Binaryテーブルはデータをすべてバイナリで持っているので、各カラムを参照する際にはconvert_fromでタイプを変換する必要があります。
今回は単純にUTF8文字列に変換します。

> select convert_from(row_key, 'UTF8'), convert_from(bt.cf1.c1, 'UTF8'), convert_from(bt.cf1.c2, 'UTF8'), convert_from (bt.cf2.c1, 'UTF8'), convert_from (bt.cf2.c2, 'UTF8') from dfs.`/user/mapr/db/binary_table_1` as bt;
+---------+----------+---------+----------+---------+
| EXPR$0  |  EXPR$1  | EXPR$2  |  EXPR$3  | EXPR$4  |
+---------+----------+---------+----------+---------+
| row0    | cf1val0  | 0       | cf2val0  | 10      |
| row1    | cf1val1  | 1       | cf2val1  | 11      |
| row2    | cf1val2  | 2       | cf2val2  | 12      |
| row3    | cf1val3  | 3       | cf2val3  | 13      |
| row4    | cf1val4  | 4       | cf2val4  | 14      |
| row5    | cf1val5  | 5       | cf2val5  | 15      |
| row6    | cf1val6  | 6       | cf2val6  | 16      |
| row7    | cf1val7  | 7       | cf2val7  | 17      |
| row8    | cf1val8  | 8       | cf2val8  | 18      |
| row9    | cf1val9  | 9       | cf2val9  | 19      |
+---------+----------+---------+----------+---------+
10 rows selected (0.388 seconds)

JSON テーブル

同様にJSONテーブルもについてもテーブルを生成するところから紹介します。

$ hadoop fs -cat /tmp/json_hive_01.json
{"_id":"0","name":"Walter White",  "prop": {"actor": "Bryan Cranston", "job":"chemistry teacher"}, "family": [ {"relation":"wife", "name": "Skyler White"}, {"name": "Walter White Jr.", "relation": "son"}] }
{"_id":"1","name":"Jesse Pinkman", "prop": {"actor": "Aaron Paul", "job":"drug dealer"}, "family" : []}
{"_id":"2","name":"Hank Schrader", "prop": {"actor": "Dean Norris", "job":"DEA agent"}, "family" :[ {"relation":"wife", "name": "Marie Schrader"}]}
{"_id":"3","name":"Saul Goodman",  "prop": {"actor": "Bob Odenkirk", "job":"layer"}, "family" : [ ]}


$ mapr importJSON -src /tmp/json_hive_01.json -dst /user/mapr/db/json_table_01

続いてクエリを実行してみます。
Binaryテーブルと同様、dfsプラグインでテーブルへのパスを指定するだけです。

> select *  from dfs.`/user/mapr/db/json_table_01` as t;
+------+-------------------------------------------------------------------------------------------+----------------+-------------------------------------------------------+
| _id  |                                          family                                           |      name      |                         prop                          |
+------+-------------------------------------------------------------------------------------------+----------------+-------------------------------------------------------+
| 0    | [{"name":"Skyler White","relation":"wife"},{"name":"Walter White Jr.","relation":"son"}]  | Walter White   | {"actor":"Bryan Cranston","job":"chemistry teacher"}  |
| 1    | []                                                                                        | Jesse Pinkman  | {"actor":"Aaron Paul","job":"drug dealer"}            |
| 2    | [{"name":"Marie Schrader","relation":"wife"}]                                             | Hank Schrader  | {"actor":"Dean Norris","job":"DEA agent"}             |
| 3    | []                                                                                        | Saul Goodman   | {"actor":"Bob Odenkirk","job":"layer"}                |
+------+-------------------------------------------------------------------------------------------+----------------+-------------------------------------------------------+

> select t.name,  t.family[0].name as spouse, t.prop.actor as actor  from dfs.`/user/mapr/db/json_table_01` as t;
+----------------+-----------------+-----------------+
|      name      |     spouse      |      actor      |
+----------------+-----------------+-----------------+
| Walter White   | Skyler White    | Bryan Cranston  |
| Jesse Pinkman  | null            | Aaron Paul      |
| Hank Schrader  | Marie Schrader  | Dean Norris     |
| Saul Goodman   | null            | Bob Odenkirk    |
+----------------+-----------------+-----------------+

クエリの中ではハッシュや配列へのアクセスも行っていますので、参考にしてください。

オプション

dfsプラグインのMapR-DB用の設定項目についてはここに触れられています。
本記事では少しだけ紹介します。

まずはJSONテーブルを作成した際のデータに'age'カラムを追加してみます。

$ hadoop fs -cat /tmp/json_hive_01.json
{"_id":"0","name":"Walter White",  "age":50, "prop": {"actor": "Bryan Cranston", "job":"chemistry teacher"}, "family": [ {"relation":"wife", "name": "Skyler White"}, {"name": "Walter White Jr.", "relation": "son"}] }
{"_id":"1","name":"Jesse Pinkman", "age":23 , "prop": {"actor": "Aaron Paul", "job":"drug dealer"}, "family" : []}
{"_id":"2","name":"Hank Schrader", "age":"unknown" , "prop": {"actor": "Dean Norris", "job":"DEA agent"}, "family" :[ {"relation":"wife", "name": "Marie Schrader"}]}
{"_id":"3","name":"Saul Goodman",  "age":"unknown" , "prop": {"actor": "Bob Odenkirk", "job":"layer"}, "family" : [ ]}

$ mapr importJSON -src /tmp/json_hive_01.json -dst /user/mapr/db/json_table_01

ご覧のように"age"カラムにInt型と文字列が混ざる好ましくない状態でimportしてしまいました。
このときデフォルトのままクエリを実行するとエラーが発生します。

> select * from dfs.`/user/mapr/db/json_table_01` as t;
Error: DATA_READ ERROR: Possible schema change at _id: '2', field: 'age'

Fragment 0:0

[Error Id: f64cf1bc-b993-494d-a2d3-5ee581bed2db on syamada-dist2:31010] (state=,code=0)

ここで dfs プラグインの設定に'allTextMode'をtrue状態で設定してみます。
これにより文字通りすべてのカラムをテキストとして扱います。

...
    "maprdb": {
      "type": "maprdb",
      "allTextMode": true
    }
...

再びクエリを実行

> > select age from dfs.`/user/mapr/db/json_table_01`;
+----------+
|   age    |
+----------+
| 50.0     |
| 23.0     |
| unknown  |
| unknown  |
+----------+

表示できるようになりました。

次に'ignoreSchemaChange'で遊んでみましょう。

...
    "maprdb": {
      "type": "maprdb",
      "ignoreSchemaChange": true
    }
...

> select age from dfs.`/user/mapr/db/json_table_01` order by age ;
+-------+
|  age  |
+-------+
| 23.0  |
| 50.0  |
+-------+

カラムのタイプが変わった行のデータが無視されるようになりました。

以上の様にデータによってはプラグインが有益/無益となりますので、いろいろ試してみましょう。
今回は以上となります。