Posted at
MapRDay 10

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

More than 1 year has passed since last update.

今回は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 |
+-------+

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

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

今回は以上となります。