HiveQL(HiveのSQLっぽい独自言語)のテーブルに関するメモ。
Hiveでは操作対象のファイル(基本的にはHDFS上のファイル)をテーブルと呼んで扱う。
「テーブル」と呼んでいても、データの実体はファイル。
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] テーブル名 [(項目名 型 [COMMENT コメント], …)] [COMMENT テーブルのコメント] [PARTITIONED BY (項目名 型 [COMMENT コメント], …)] [CLUSTERED BY (項目名, …) [STORED BY (項目名 [ASC|DESC], …)] INTO バケット数 BUCKETS] [ROW FORMAT 行フォーマット] [ STORED AS ファイルフォーマット] | STORED BY 'クラス名' [WITH SERDEPROPERTIES (〜)] ] [LOCATION パス] [TBLPROPERTIES (プロパティー名=値, …)] [AS SELECT文]
HiveのテーブルはCREATE TABLEで作成する。
create table テーブル名 ( 項目名 型, … );
HiveQLはSQL(RDBMS)に似せているためHive上の扱いは“テーブル”だが、実体は(HDFS上の)ファイル。
(Hadoopを単独環境で動かしている場合はローカルのファイル)
create文を実行した時点で、(HDFSあるいはローカルの)/user/hive/warehouseの下にディレクトリー(データ置場)が作られる。
「create table」で作成したテーブルは、dropを実行するとデータ置場のディレクトリーも削除される。
CREATE TABLEにEXTERNALを付けると、ディレクトリー(データ置場)を指定してテーブルを作成する。
create external table テーブル名 ( 項目名 型, … ) location 'フルパス';
locationによる場所指定はディレクトリーであってファイルではないので、注意。
create文を実行した時点でディレクトリーが存在しなければ作られる。ディレクトリーが存在していれば何もしないが、それがファイルだったらエラーになる。
テーブルにデータを入れると、指定したディレクトリーの中にファイルが作られることになる。
後から手動でファイルを追加すると、データが追加された状態になる。(ファイルの中身がテーブル定義と一致しているかどうかは、selectしたときに(毎回)チェックされる)
「create external table」で作成したテーブルは、dropを実行してもデータ置場のディレクトリー・ファイルは削除されない。
CREATEの「ROW FORMAT」で行フォーマットを指定する。
ファイルを読み込むときにこのフォーマットに従って項目値を分割する。
create table テーブル名 〜 ROW FORMAT DELIMITED [ FIELDS TERMINATED BY ','] [ COLLECTION ITEMS TERMINATED BY ':'] [ MAP KEYS TERMINATED BY '='] [ LINES TERMINATED BY '\n'] ;
または
ROW FORMAT SERDE 'SerDeクラス名' [WITH SERDEPROPERTIES(プロパティー名=値, …)]
構文 | 説明 | 例 | ファイルの データ例 |
---|---|---|---|
FIELDS | フィールド(項目)の区切り文字を指定する。 デフォルトは0x01。テキストにとっては区切り文字無しと同義。[/2011-08-11] すなわち、データをロードすると一行分のデータが1つ目の項目に全て入り、 2つ目以降の項目はNULLになる。 →テキストファイルに出力する際の注意点 |
create table f( |
aa,bb |
COLLECTION ITEMS | コレクション(配列)の区切り文字を指定する。 デフォルトは区切り文字無し。すなわち、データをロードすると 1項目分のデータが全て配列の1個目の要素(全体として要素数が1)となる。 |
create table c( |
aa:bb:cc:dd |
MAP KEYS | マップのキーと値の区切り文字を指定する。 デフォルトは区切り文字無し。すなわち、データをロードすると 1項目分のデータが全てキーとなり、値はNULLとなる。 |
create table m( |
aa=zzz |
LINES | 行の区切り文字を指定する。 と言いつつ、Hive0.7.1でサポートされているのは「\n」のみらしい^^; |
create table L( |
aa |
SERDE | SerDe(シリアライズ・デシリアライズ)のクラスを指定する。 | create table s( |
CREATEの「STORED AS」でファイルフォーマットを指定する。
デフォルトはTEXTFILE。
create table テーブル名 〜 STORED AS フォーマット名;
フォーマット名 | 説明 | 備考(SerDe・InputFormat・OutputFormatクラス) |
---|---|---|
TEXTFILE | データをテキストファイルとして扱う。 (OutputFormatがHadoopデフォルトのTextOutputFormatでないのは、 TextOutputFormatではキーとテキストを出力するからだろう。 Hiveでは行フォーマットに従って加工したテキストのみを出力する) →テキストファイルに出力する際の注意点 |
org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe |
SEQUENCEFILE | データをシーケンスファイル(HadoopのSequenceFile)として扱う。 シーケンスファイルは任意のキーと値のペアでデータを保持する形式だが、 Hiveでは特定のクラスのみに限定している。 |
org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe |
RCFILE |
org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe |
|
INPUTFORMAT クラス OUTPUTFORMAT クラス |
InputFormat・OutputFormatのクラスを指定する。 |
ファイルフォーマットにTEXTFILEを指定した場合、実際に保存されるファイルはベタのテキストファイルとなる。[2011-08-11]
テーブルに書き込んだデータは行フォーマットに従って加工してファイルへ保存され、
読み込むときはその都度ファイルの内容を行フォーマットに従って解釈(項目毎に分割)する。
したがって、区切り文字に指定されている文字がデータに含まれていると、書き込み時と読み込み時で結果が異なることになる。
例えば行フォーマットでフィールドをカンマ区切りにしたとする。 |
create table f (f1 string, f2 string) row format delimited fields terminated by ','; |
|
ここで右記のようなデータ書き込みを行うと |
insert overwrite table f select 'aa,bb', 'cc' from dual; |
注)dualという1行しか入っていないテーブルがある前提 |
ファイルの中は右のような状態になる。 |
aa,bb,cc |
|
読み込むときはカンマ区切りとして解釈するので、 第1項目がaa、第2項目がbbで残りは捨てられる。 |
hive> select * from f; OK aa bb |
|
もっと言えば、行区切りは改行コード「\n」なので それを挿入データに指定すると ファイルの中にも改行コードが出力され、 読み込む際には複数レコード存在している状態になる。 |
insert overwrite table f select 'aa,bb', '\ncc,dd\nee,ff' from dual;↓ファイルの中身 aa,bb, cc,dd ee,ff hive> select * from f; OK aa bb cc dd ee ff |
シーケンスファイル(SequenceFile)という形式自体はHadoopで定義されている。(キーと値をそれぞれ任意のWritableで保持する形式)
だが、HiveのSEQUENCEFILEではキーは無視される(どんな型が入っていてもよい)。そして、値もText(またはBytesWritable)のみとなる。
ファイル形式でSEQUENCEFILEを指定した場合、キーは、読み込み時は無視され、書き込み時はBytesWritableの定数が出力される。
そして値は各項目を行フォーマットに従って“1つの文字列”に整形し、それが“1つのText”として出力され、読み込まれる。
(そのテキスト内のフィールド(項目)の区切りはデフォルトでは0x01、「FIELDS TERMINATED BY」が指定された場合はその文字で区切られる)
結局、TEXTFILEを指定した場合のテキスト(文字列)をシーケンスファイルの値として入出力している、という感じ。
→独自のWritableを扱いたい場合はSerDeを作成する
別のテーブル定義をコピーして新しい(空の)テーブルを作成する。
create table テーブル名 like 元テーブル名; create external table テーブル名 like 元テーブル名 location 'フルパス';
別のテーブル(の定義とデータ)をコピーして新しいテーブルを作成する。
create table テーブル名 as select 〜 from 元テーブル名 where 条件;
※コピーされる定義は項目名・データ型くらいで、その他の情報(SerDe等)は引き継がれない。[2011-08-12]
SHOW TABLESでテーブル一覧を表示する。
show tables; show tables '検索条件';
正規表現でテーブル名の検索条件を指定することが出来る。
正規表現なので「.*
」が任意の文字列という意味になり、例えば「t.*
」はtから始まるテーブルということになる。
DESCRIBEでテーブルの情報を表示する。DESCRIBEは省略して「DESC」を使用可能。
desc テーブル名; desc extended テーブル名; desc formatted テーブル名;
descのみだと、項目(と型)の一覧を表示するのみ。
extendedを付けると、詳細情報が表示される。
formattedを付けると、詳細情報が整形された分かりやすい状態で表示される。
「テーブル名.
項目名」で項目の情報が表示される。
ALTER TABLE RENAMEでテーブル名を変更できる。
alter table テーブル名 rename to 新テーブル名;
DROP TABLEでテーブルを削除する。
drop table テーブル名; drop table if exists テーブル名;
CREATE TABLEで作ったテーブルは、dropするとデータ置場のディレクトリーも削除される(データファイルが消える)。
CREATE EXTERNAL TABLEで作ったテーブルは、dropしてもデータ置場のディレクトリー(およびファイル)は削除されずそのまま残る。