Hiveのベストプラクティス(かもしれないこと)をめもっておく
Hiveの現場に来て4か月経ち回りのやり方を観察したり、他の事例を調べたりしているうちにHiveを使用する際のパターンというかベストプラクティスが見えてきた気がするので書いてみるよ。
ユースケースはログ解析です。
1. ファイルフォーマットと圧縮
ログは圧縮率高いので圧縮すべし。でもスプリット可能であるためにはってことでSequenceFileでブロック圧縮は確定。
圧縮コーデックは圧縮率を考えてgzip。
ちなみに圧縮率は
bzip2>gzip>LZO
でスピードは
LZO>gzip>bzip2
だ。bzipはスプリット可能で圧縮率も高いんだけどHadoop 0.20系ではまだ使えなかったと思う。Hadoop 0.20系でも使えるらしいですが遅くて使い物にならないようです。
最近はsnappyなんてのも出ててCDH3 Update 1で使えるようになりましたね。
snappyは圧縮率はLZO並みだけどスピードが早いらしい。
Mapの出力は一時的なものなのでここはスピード優先でLZOもしくはsnappyを使うといいかもしれない。
また古くて使わなそうなデータは圧縮率高いbzip2で圧縮してアーカイブするといいかも。
2. 初期データは外部テーブルで保存
Hiveに最初に投入されるデータは外部テーブルが良い。
外部テーブルと普通のテーブルの違いはテーブルのDROP時に前者はメタデータだけが削除されデータは削除されないのに対して、後者はメタデータもデータも両方削除される。
Hiveに最初に投入される初期データは生データに近いはずで、データに不備があった場合にSELECT文じゃなくてhadoop fs -textで見たい場合がある。
例えばタブ区切りで200列のはずが201列になってたようなケースではSELECT文では不正なデータの調査ができない。この場合はhadoop fs -textで見る。
外部テーブルにしなくても見れるけど外部テーブルのほうが1ファイルになってて何かと都合がいいだろう。
それ以外の理由としては、初期データをHive以外から見たいというケースがあるかもしれないからだ。最初はHiveで解析してたけど違うこともやりたいってなったときにとりあえずHDFSに突っ込んでおいてHiveからは外部テーブル経由でアクセスして、他の用途では別の方法でアクセスしたりできるようにしとくのがよい。
HiveによるETL処理が進んだ中間テーブルはどうせHiveでしかアクセスしないだろうから、この辺りは普通のテーブルでよい。
ま、この辺も象本2版の12.6.1に書いてある。
3. パーティションは必須
ま、これは当たり前かな。そうしないと追記できないからね。日付でパーティションするのは必須であとは必要に応じてって感じかな。
4. 処理は冪等に
冪等とは、ある操作を1度行っても複数回行っても同じ効果となることを言います。数学的な記号を使うとこんな感じ。P*P=P
データを作る場合はINSERT OVERWRITEでパーティションにデータを突っ込むようなETL処理がほとんどだと思うので冪等になると思います。
冪等ならば元データが不正で作り直す場合も元データ直してリトライすればいいだけです。
5. RDBMSのデータとの結合は先延ばし
Hiveでログ解析する場合はたいていログ以外にRDBMS上にマスターデータがあってそれと結合したいはずです。
ETL処理の最初のほうのフローでマスターデータと結合しちゃうと、マスターデータが変わった場合に一連の処理を全部やり直すはめになります。なのでなるべく先延ばしがいいと思います。
またHiveで作ったデータをRDBMSに持っていってそこで結合する場合は、あらかじめ集約しておくなどしてデータ量を減らしてRDBMSに持っていくほうが無難でしょう。
またHiveとは直接関係無いけどログ解析という意味では下記のスライドも参考になります。