CUBE SUGAR CONTAINER

技術系のこと書きます。

Apache Hive 1.x の INSERT 文の仕様でハマった話

今回は、タイトルの通り 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)

いじょう。

ビッグデータ分析・活用のためのSQLレシピ

ビッグデータ分析・活用のためのSQLレシピ

プログラミング Hive

プログラミング Hive

  • 作者: Edward Capriolo,Dean Wampler,Jason Rutherglen,佐藤直生,嶋内翔,Sky株式会社玉川竜司
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2013/06/15
  • メディア: 大型本
  • この商品を含むブログ (3件) を見る