今回は、タイトルの通り Apache Hive の 1.x を使っていたとき INSERT 文の仕様でハマった話。
先に概要を説明しておくと Apache Hive の 1.x と 2.x ではサポートする構文が変わっている。
具体的には 1.x では INSERT INTO ... SELECT
文で後続に FROM ...
が必要なんだけど 2.x ではそれが不要になっている。
使った環境は次の通り。 ディストリビューションやマネージドサービスは特に使わずに構築してある。
$ cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core) $ uname -r 3.10.0-862.3.2.el7.x86_64 $ hive --version Hive 1.2.2 Subversion git://vgumashta.local/Users/vgumashta/Documents/workspace/hive-git -r 395368fc6478c7e2a1e84a5a2a8aac45e4399a9e Compiled by vgumashta on Sun Apr 2 13:12:26 PDT 2017 From source with checksum bd47834e727562aab36c8282f8161030 $ hadoop version Hadoop 2.9.1 Subversion https://github.com/apache/hadoop.git -r e30710aea4e6e55e69372929106cf119af06fd0e Compiled by root on 2018-04-16T09:33Z Compiled with protoc 2.5.0 From source with checksum 7d6d2b655115c6cc336d662cc2b919bd This command was run using /home/vagrant/hadoop-2.9.1/share/hadoop/common/hadoop-common-2.9.1.jar
まずは Hive のシェルを起動しておく。
$ hive
続いて、動作確認に使うテーブルを定義する。
hive> CREATE TABLE example_table ( > message STRING > ); OK Time taken: 0.059 seconds
ここで INSERT INTO ... SELECT
構文を使ってデータを追加してみよう。
すると、以下のようなエラーになってしまう。
hive> INSERT INTO TABLE example_table > SELECT "Hello, World"; ... FAILED: ParseException line 2:21 Failed to recognize predicate '<EOF>'. Failed rule: 'regularBody' in statement
上記のエラーメッセージで検索しても「スキーマ定義で予約語を使ってるんじゃない?」みたいな関係ないものしか出てこない。
実際には Apache Hive 1.x の場合 INSERT INTO ... SELECT
に続いて FROM
がないとエラーになるのが原因。
以下ではサブクエリを使って無意味な FROM
を無理やり追加することで解決している。
hive> INSERT INTO TABLE example_table > SELECT "Hello, World" > FROM (SELECT "dummy") dummy; ... OK Time taken: 16.697 seconds
これでちゃんとレコードが追加できた。
hive> SELECT * FROM example_table; OK Hello, World Time taken: 0.059 seconds, Fetched: 1 row(s)
ちなみに INSERT INTO ... VALUES
を使えば FROM
なしでレコード追加ができる。
hive> INSERT INTO TABLE example_table > VALUES ("Hello, World 2"); ... OK Time taken: 17.4 seconds hive> SELECT * FROM example_table; OK Hello, World Hello, World 2 Time taken: 0.034 seconds, Fetched: 2 row(s)
じゃあ INSERT INTO ... SELECT
なんか使わなければいいじゃん!ってなるんだけど、そうもいかない場合がある。
まず、一つ目の理由は設定か何かで解決できると思うんだけど INSERT INTO ... VALUES
を使うとテンポラリなテーブルが作られる。
hive> SHOW TABLES; OK example_table values__tmp__table__1 Time taken: 0.008 seconds, Fetched: 2 row(s)
中身はレコードを追加するときに使って VALUES
以降の内容になっている。
hive> SELECT * FROM values__tmp__table__1; OK Hello, World 2 Time taken: 0.031 seconds, Fetched: 1 row(s)
まあ上記は良いとして問題がもう一つあって。
複合型 (STRUCT や ARRAY など) を使おうとすると INSERT INTO ... VALUES
だとレコードが追加できない。
hive> CREATE TABLE example_table_with_array ( > messages ARRAY<STRING> > ); OK Time taken: 0.032 seconds
複合型が含まれるレコードを INSERT INTO ... VALUES
で追加しようとすると、次のようなエラーになる。
hive> INSERT INTO TABLE example_table_with_array > VALUES (ARRAY("Message1", "Message2")); FAILED: SemanticException [Error 10293]: Unable to create temp file for insert values Expression of type TOK_FUNCTION not supported in insert/values
INSERT INTO ... SELECT
ならエラーにならない。
hive> INSERT INTO TABLE example_table_with_array > SELECT ARRAY("Message1", "Message2") > FROM (SELECT "dummy") dummy; ... OK Time taken: 17.318 seconds hive> SELECT * FROM example_table_with_array; OK ["Message1","Message2"] Time taken: 0.072 seconds, Fetched: 1 row(s)
なので INSERT INTO ... SELECT
を使うことになる。
Apache Hive 2.x の場合
ちなみに最初に記述した通り Apache Hive 2.x では FROM
をつけなくても良くなっている。
実際に環境を用意して試してみよう。
$ hive --version Hive 2.3.3 Git git://daijymacpro-2.local/Users/daijy/commit/hive -r 8a511e3f79b43d4be41cd231cf5c99e43b248383 Compiled by daijy on Wed Mar 28 16:58:33 PDT 2018 From source with checksum 8873bba6c55a058614e74c0e628ab022 $ hadoop version Hadoop 2.9.1 Subversion https://github.com/apache/hadoop.git -r e30710aea4e6e55e69372929106cf119af06fd0e Compiled by root on 2018-04-16T09:33Z Compiled with protoc 2.5.0 From source with checksum 7d6d2b655115c6cc336d662cc2b919bd This command was run using /home/vagrant/hadoop-2.9.1/share/hadoop/common/hadoop-common-2.9.1.jar
複合型が含まれるテーブルを定義する。
hive> CREATE TABLE example_table_with_array ( > messages ARRAY<STRING> > ); OK Time taken: 8.459 seconds
Apache Hive 1.x ではエラーになった INSERT INTO ... SELECT
を発行してみよう。
hive> INSERT INTO TABLE example_table_with_array > SELECT ARRAY("Message1", "Message2"); ... OK Time taken: 28.527 seconds
今度はエラーにならない。
ちゃんとレコードも追加されている。
hive> SELECT * FROM example_table_with_array; OK ["Message1","Message2"] Time taken: 0.223 seconds, Fetched: 1 row(s)
いじょう。
- 作者: 加嵜長門,田宮直人
- 出版社/メーカー: マイナビ出版
- 発売日: 2017/03/27
- メディア: Kindle版
- この商品を含むブログを見る
- 作者: Edward Capriolo,Dean Wampler,Jason Rutherglen,佐藤直生,嶋内翔,Sky株式会社玉川竜司
- 出版社/メーカー: オライリージャパン
- 発売日: 2013/06/15
- メディア: 大型本
- この商品を含むブログ (3件) を見る