kanga333.log

雑な記録

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'

これにより参照を止めることなく、データの作り直しが可能になる。