きわめてざっくり書くと以下のような感じ
- 同じようなクエリを発行しているふたつの出力の圧縮方法が違う
- そもそもこれは何故起きるのか?
hiveむづかしい。
(あとで書いた) TextFile だとファイル全体で圧縮がかかって、SequenceFile だと mapred.output.compression.type の指定に従って圧縮を行うわけですね。SequenceFileを扱う場合はこれを BLOCK とかにしておくと圧縮効率が上がります。というか、そうしないと圧縮効率が下がって悲しいことになります。
ということでした! わかった!
詳細
定期的に他のテーブルから1日分のデータをまとめたりしてdailyのテーブル(のパーティション)を編成してる。流れとしては以下のような感じ。
- hourlyでパーティションをつくっているテーブルから24時間分をまとめて daily (full) のテーブルに1パーティションとしてINSERT
- daily (full) の1パーティション(1日分)から特定の条件でSELECTをかけ、一部分を抽出して daily (part) のテーブルに1パーティションとしてINSERT
このとき、前者より後者の方がデータは少ない(レコードを選別してるし、フィールドも一部のもののみ取り出している)ので後者のデータサイズが小さくなることを当然期待したが hadoop fs -du してみるとそうなってない。あれー?
ということで調べてみたら、以下のようになっていた。
- daily (full) の方は各パーティション内のファイルは 00000_0.gz のようなファイル名になっており、ファイル全体がgzip圧縮されている
- daily (part) の方は各パーティション内のファイルは 00000_0 のようなファイル名になっている
- 中身を見ると 以下のようなヘッダで始まっている
SEQ"org.apache.hadoop.io.BytesWritableorg.apache.hadoop.io.Text'org.apache.hadoop.io.compress.GzipCodec
まったく同じ設定で連続して発行したふたつのクエリでなぜこうなるのか。テーブル定義は両方とも STORED AS SEQUENCEFILE に
……なってなかった!!!!! ここまで書いて気付いた! daily (full) のテーブルは STORED AS TEXTFILE だった!!!!!!
結論
mapred.output.compression.type はちゃんと BLOCK とかで指定しておきましょう。デフォルトの RECORD はたいへん効率わるいです。