Hiveによるデータの洗い替え処理の検証
目的
Hiveによってデータを洗い替えする際の処理パターンを検討する
はじめに
Hive、というよりHDFSにおいてデータはimmutableな物として扱ったほうが良い。 パフォーマンスの観点から追記や更新を表現するような処理パターンは避けた方が無難である。 なぜならHDFSはHDD上に大量のデータをシーケンシャルに一気に書き込む事でパフォーマンスを稼ぐ事を前提に設計されているためである。 追記のような処理あるいは部分更新を実現するために過剰なパーティション構造にすると、細分化されたファイルが大量にできる。 細分化されたファイルはランダムリードの増加やNameNodeの負荷増加に繋がる。 更新や追記をヘビーに使いたい用途においてはHBaseやKuduを使った方が良い。 しかし、処理によってはどうしてもHDFS上のデータを更新したいケースが出てくる。
そういたケースでは、対象のデータあるいはパーティションをまるっと作り直した方が、参照のパフォーマンスは良くなる。 もちろん対象のデータセットのサイズにもよるが、十分大きいクラスタであれば大概のデータは作り直せる。
洗い替え処理
前提として対象データはExternalテーブルとする。 まず対象データのDDLにおいて通常の処理で利用するパーティション階層に加えてversionというパーティションを加える。
CREATE EXTERNAL TABLE access_log ( remote_host STRING, ident STRING, user STRING, time STRING, raw_request STRING, respons_code INT, byte INT, referrer STRING, user_agent STRING, response_time_microsecond INT, host STRING ) PARTITIONED BY(dt STRING, version STRING) STORED AS ORC LOCATION '/data/kanga333/access_log/';
そして適当なクエリでデータを挿入する。(以下のクエリは一例。わかりやすさのためdtを明示的な値として渡している)
FROM access_log_origin INSERT OVERWRITE TABLE access_log partition(dt, version) SELECT *, '20180101', '1';
作成したテーブルはHDFSから見ると以下のようなディレクトリ構造となる。
/data/kanga333/access_log/dt=20180105/version=1
この状態において以下のクエリを実行し、HDFS上にエイリアスのパーティション’latest’を作成する。
ALTER TABLE access_log ADD PARTITION (dt = '20180101', version = 'latest') location '/data/kanga333/access_log/dt=20180101/version=1'
基本的に該当テーブルに対する参照クエリはversionパーティションをlatestに指定してクエリを実行する。
SELECT count(*) FROM access_log WHERE dt = '20180101' AND version = 'latest'
データを作り直したくなった場合はversionパーティションをインクリメントして新しいパーティションを作成する。
FROM access_log_origin INSERT OVERWRITE TABLE access_log partition(dt, version) SELECT *, '20180101', '2';
その後、latestパーティションの向き先をalterにより変更する。
ALTER TABLE access_log PARTITION (dt = '20180101', version = 'latest') SET LOCATION '/data/kanga333/access_log/dt=20180101/version=2'
これにより参照を止めることなく、データの作り直しが可能になる。