Apache Iceberg: The Definitive Guideの読書メモ
dremio
ってとこが、Apache Iceberg: The Definitive Guide`を無償公開してくれてたのにあやかって、読んでみた。
公式サイト
テーブル仕様
TL;DR
Part Iは基本編
- 大抵の内容は誰かが日本語位ブログでまとめてくれてたり、クラウドベンダの提供するドキュメントと丸かぶりしてる印象。
- 1章:イントロ
- 5章: カタログのメリ/デメとユースケースは割と手厚く書かれてたので、ここは読む価値あり
Part IIはハンズオンなのでスキップ
Part IIIは応用編
- ちょっと情報が古くなりつつある感じだったので軽く読み流した程度。
- 公式サイトのリンクを載せておくので、詳細はそっちを見てねというスタンス。
1章 Introduction
OLTPとOLAP
OLTP
- 行単位での記録・更新がメイン
-
day by day
なデータの取得には最適
-
- 正規化をよしとする
- 大量の履歴データの集約するよう設計されてはいない
OLAP
-
列単位での集約がメイン
- カラムナ構造がより適している
-
非正規化した方がより良く実行できる
-
OLTPとOLAPの実行リソースの取り合いとなる
OLAPの構成要素
Storage
- 巨大なデータセットに対して分析クエリを扱うシステムに必要
- ローカルストレージ
- DAS (Direct Attached Storage)
- 分散ストレージ
- HDFS(Hadoop Distributed File System)
- Amazon S3
- データベース
- 行指向
- 列指向
- ローカルストレージ
File Format
- ファイルの圧縮、データ構造、性能に影響する
- 構造化データ
- CSV
- 半構造化データ
- JSON
- 非構造化データ
- プレーンテキスト
- 行指向フォーマット
- Apache Avro
- 一度に少数のデータを扱うのに向いている
- 列指向フォーマット
- Apache ORC
- 一度に大量のデータを扱うのに向いている
- 構造化データ
Table Format
- 構造化の方法を定義
- 保存されたファイルに対するメタデータ
- 物理ファイルの構造の抽象化
Storage Engine
-
Table Format
を介してStorage
からファイルを取得する - 物理的な最適化
- ストレージのインデックス管理
- 古いデータの除外
Catalog
- メタデータの管理
Compute Engine
- 分析基盤
- 分散分析基盤
- MPP (Massively Parallel Processing)
- Apache Spark
- Snowflake
- Dremio
- MPP (Massively Parallel Processing)
- 分散分析基盤
Data warehouse
- 単一システムに
OLAP
コンポーネントが密結合で組み込まれている - コンポーネントがベンダーロックインされている
- 構造化データのみが対象
- 半構造、非構造データは別の手段が必要
- ワークフローを組み立てる必要がある
- ETL
Data warehouseの歴史
- 〜2015: コンポーネントが一つのオンプレミス環境のノードに密結合
- スケールアウトできない
- 2015以降: 各々のコンポーネントがクラウド環境に分散して置かれるようになった
Data lake
- メリット
- 安価
- 非ベンダーロックイン
- デメリット
- インデックスやACID特性を持たない
Data lakeのはじまり
-
Hadoop
+HDFS
で構造、半構造、非構造問わずストレージに格納 -
MapReduce
ジョブで分析の実行 - Hive
-
SQL
をMapreduce
ジョブに変換する
-
- Hive Table Format
- ファイルやフォルダそのものををテーブルとみなして扱う
- テーブルとファイルが
1:1
- テーブルとファイルが
- メリット
- パーティショニングによりフルスキャンよりも効率的に探索できる
- デメリット
- ファイル単位の差し替えができない
- 並行的に同時制御できない
- 統計情報が非同期ジョブで収集されるため、クエリの最適化が困難
- ファイルやフォルダそのものををテーブルとみなして扱う
クラウドオブジェクトストレージの登場
- Amazon S3
- Minio
- Azure Blog Storage
分散管理されたファイルを扱うのにHive Table Format
は向いていない
分散クエリエンジン
- Apache Spark
- Presto
- Dremio
Data lakehouse
- Data warehouseとData lakeのいいとこどり
-
Table Format
のメタデータを使用して、整合性、性能、ACID特性のための抽象レイヤを提供する- ACID特性を持つことにより、トランザクション単位でコピーを持つことが不要になる
- メタデータのインデックスやフィルタで素早くデータにたどり着く
- スナップショットをもつため前のバージョンへのロールバックも容易
- Open Architectureを使用
- Modern Table Format
- Apache Iceberg, Hudi, Delta lake
- ファイルに付与されるメタデータでTable Formatを形作る
- ACIDや
time travel
を可能にした - 統計情報をメタデータとして保持
- ACIDや
- ファイルに付与されるメタデータでTable Formatを形作る
- Apache Iceberg, Hudi, Delta lake
- File Format
- Apache Parquet
- Modern Table Format
Apache Iceberg
- マルチパーティションに置かれたテーブルの整合性を自動的に解決
- メタデータを使用して素早くファイルを列挙
- テーブル(ファイル)構造を意識することなくパーティションにフィルタを完遂させる
- スキーマ進化
- メタデータを再作成することなくスキーマの更新を達成する
- ペタバイトスケールのデータで達成する
コンポーネントレイヤー
データレイヤー
- Data File
- 実データ
メタデータレイヤー
- Manifest File
- データファイルパス、メタデータを保持
- Manifest List
-
Manifest File
のリストとしてテーブルのスナップショットを保持
-
- Metadata file
- テーブルスキーマ、パーティションスキーマ、スナップショットのリストの定義を保持
カタログレイヤー
- catalog
- 最新の
Metadata File
を追跡するためのファイル
- 最新の
ACID特性
- 楽観的整合性をもってACID特性を保証
- ロック期間の最小化
- 悲観的整合性は未サポート
- 整合性の保証は
Catalog
が取り仕切る
パーティション進化
- すべてのテーブルを変更することなくパーティション定義を変更できる
隠しパーティション
- パーティション変換変数に基づいた物理パーティショニング
- パーティション変換変数 -
event_year
,event_month
,event_day
など - パーティションのためのカラムをテーブルに追加する必要はない
- パーティション変換変数 -
行レベル操作
- COW (Copy-on-Write)
- 行が変更された際、新しいファイルを作成する
- 更新は遅いが検索は早くなる
- MOR (Merge-on-Read)
- 変更箇所の差分のみを保持するファイルを作成する
- 更新は早くなるが検索は遅くなる
- 削除情報は
Delete File
を作成する(v2以降でサポート)
Time Travel
- スナップショットを作ることで、任意時点でのテーブルにアクセスできる
- 任意時点のスナップショットに巻き戻すことも可能
スキーマ進化
- テーブルスキーマの容易な変更
2章 Architecture
Icebergのコンポーネントレイヤー
Catalog layer
- 最新の
Metadata File
を指し示す - 使用する分散ストレージごとに
Catalog
定義は異なる- Amazon S3
-
version-hint.text
に記録
-
- Hive
-
Hive Metastore
のlocation
フィールドに記録
-
- Nessie
-
metadataLocation
フィールドに記録
-
- Amazon S3
Metadata layer
- メタデータをツリー構造で管理
- Metadata File(ルート) > Manifest List > Manifest File
- Metadata File
- テーブルスキーマ
- パーティション情報
- Manifest List
-
Iceberg
テーブルのスナップショットを保持- 時系列で
Manifest File
とマッピング
- 時系列で
- パーティション境界
- スナップショットの統計情報
- 最大値、最小値、合計行数、合計削除行数など
-
- Manifest File
-
Data File
(実データ、削除データ)とマッピング - 複数の
Data File
に対する統計情報- 抽出の際の枝刈りに使用される
-
Data File
の作成と並行して作られる
- 統計情報
- 最大値、最小値、行数
- パーティションの振り分け先
-
- Puffine File
-
Manifest File
には記録されない付加的な統計情報 - インデックス
-
Data layer
- テーブルの実データとなる
Data File
を格納するレイヤー- 任意のファイルフォーマットのファイルを格納できる
- OLAP向けフォーマット
- Apache Avro
- 行指向
-
JSON
で定義されたスキーマに基づいてしリアライズする - 小規模低レイテンシーな分析と相性が良い
- Apache ORC
- 行指向と列指向の合いの子
- Apache Parquet
- 列指向
- 大規模OLAPと相性が良い
- データは
Row Group
>Column
>Page
の順に細分化されて保持
- Apache Avro
- 削除情報のここに置かれる
- Positional Delete File
- 対象行を論理削除としてマークする
- 単一行ごとにマーク
- Equallity Delete File
- 削除条件を用いて論理削除としてマークする
- 複数行を一括でマークできる
- Positional Delete File
- 実運用では分散ファイルシステム
- HDFS, Amazon S3, Azure Datalake Storage, Google Cloud Storageなど
3章 Lifecycle
クエリエンジンから見たコンポーネントレイヤー
Catalog layer
- クエリエンジンが最初に参照するコンポーネント
- read
- 現在のテーブルの状態をチェックする
- write
- テーブルスキーマの参照
- パーティションスキーマの参照
Metadata layer
- write
- 新しい
metadata file
が作成される
- 新しい
- read
-
manifest list
を参照してパーティション情報を取得する- フィルタリングに使用
-
manifest file
を参照して統計情報(最大値、最小値、NULL件数等)を取得する- フィルタリングに使用
-
Data layer
- write
-
Metadata layer
を参照することで決定したファイルを作成戦略(CoW, MoW)に基づいて作成する - 作成後、
metadata file
を遡って順次更新していく
-
- read
-
Metadata layer
を参照することで決定したファイルを読む
-
Write処理
-
SQL
のパース -
catalog layer
からスタートして、書き込むファイルを決定する - パーティションや作成戦略に基づいて、
Data layer
にファイルを作成する -
Manifest file
>Manifest list
>Metadata file
の順にMetadata layer
の情報を更新する -
Catalog layer
の指し先を最新化する
テーブル作成
-
SQL
のパース - カタログの管理先に
v1.metadata.json
を作成しテーブル情報を格納する - テーブルパス情報に基づいて
Manifest file
を作成する- 一意的なIdを付与する(
table-uuid
) - カラム名や型定義を格納
- 一意的なIdを付与する(
-
Catalog layer
の指し先を最新化する
Insertクエリ
-
SQL
のパース - カタログを参照してテーブルの存在チェック
- 対象の
Metadata file
の決定 - パーティションの決定
- 対象の
- パーティション戦略に基づいて
Data layer
ファイルを作成- テーブルにクラスタ化インデックスが指定されていれば、先にソートする
-
Manifest file
を作成する- 作成したファイルパスを記録
- 統計情報の記録
- 最大値、最小値、NULL件数等
-
Manifest file
のファイルフォーマットはavro
- ファイルは楽観的整合性で作成する
- 同時実行の衝突を保証しない
-
Manifest list
を作成する-
Manifest file
のパスを記録 - 統計情報の記録
- 追加行数
- パーティション境界
-
-
Metadata file
を作成する - 整合性チェックを行う
-
Catalog layer
の指し先を最新化する
Mergeクエリ(Upsert/Merge)
-
SQL
のパース - カタログを参照してテーブルの存在チェック
- 対象の
Metadata file
の決定 - パーティションの決定
- 対象の
- 対象ファイルをメインメモリに展開し、更新行を決定する
- データファイルを作成する
- 内容は作成戦略(CoW, MoR)に従う
-
Manifest file
を作成する- 新しく作成されたファイルのパスを記録
-
Insert
同様統計情報も記録 -
Manifest file
のファイルフォーマットはavro
-
Manifest list
を作成する- 新しく作成された
Manifest file
のパスを記録
- 新しく作成された
-
Metadata file
を作成する - 整合性チェックを行う
-
Catalog layer
の指し先を最新化する
Selectクエリ
-
SQL
のパース - カタログを参照してテーブルの存在チェック
- 対象の
Metadata file
の決定 - パーティションの決定
- 対象の
-
Metadata file
を読み各種情報を取得する- テーブルスキーマ
- パーティションスキーマ
current-snapshot-id
-
current-snapshot-id
に基づいてManifest list
を読み各種情報を取得する-
Manifest file
のパス -
partition-spec-id
- パーティションスキーマのId
- 統計情報
- パーティション境界
-
-
Manifest file
を読み各種情報を取得する- クエリの
Where
句とパーティション境界や統計情報を比較してDaqta file
を決定する
- クエリの
- マテリアライズされた結果を返す
Time-Travelクエリ
- Time-Travel戦略
- timestamp
- snapshot-id
-
SQL
のパース - カタログを参照してテーブルの存在チェック
- 対象の
Metadata file
の決定 - パーティションの決定
- 対象の
-
Metadata file
を読み各種情報を取得する- テーブルスキーマ
- パーティションスキーマ
-
snapshot-id
の決定
-
snapshot-id
に基づいてManifest list
を読み各種情報を取得する-
Manifest file
のパス - 統計情報
- パーティション境界
-
-
Manifest file
を読み各種情報を取得する- クエリの
Where
句とパーティション境界や統計情報を比較してDaqta file
を決定する
- クエリの
- マテリアライズされた結果を返す
4章 最適化
コンパクション
- ファイルからデータを読み出すコスト(固定コスト)
- 回避不可能なコスト
- ファイルにアクセス(open, close)コスト(可変コスト)
- ファイル数に比例して増えるコスト
- ファイルを併合することで減らすことが可能
コンパクション戦略
- rewriteDataFiles手続きで使用可能となる戦略
- binPack
- ファイルの併合
- sort
- クラスター化インデックスの変更
- zOrder
- filter
- 追加の絞り込み条件を指定
- option / options
- jobの実行構成を変更する
- binPack
パーティション進化
- パーティションを追加 / 削除する
作成戦略
- CoW
- レコード更新に伴うファイル作成は遅い
- 対象ファイル数が減るため読み込みは他の戦略に比べて速い
- MoR (position deletes)
- 他2つの戦略の間の性能
- MoR (equallity deletes)
- 差分のみ含めたファイル作成のため書き込みは早い
- 複数のファイルの走査が必要になるため読み込みは遅い
統計情報
- 統計内容をカスタマイズすることで、ファインチューニングできる
ストレージの最適化
- 不要になったスナップショットを無効化する
5章 Catalog
Hadoop Catalog
- 外部システムやプロセスを必要としないカタログ
- 多くのファイルシステムをサポート
- HDFS
- アトミックなリネームをサポート
- Amazon S3
- Azure Datalake Storage
- アトミックなリネームをサポート
- Google Cloud Storage
- HDFS
- 最新の
Metadata file
へのパスにマッピングする方式- マッピングは、
version-hint.txt
にMetadata file
のパスに含まれるバージョンを記録
- マッピングは、
メリット
- 外部システムやプロセスが不要
デメリット
- 複数のジョブによる並行的なアクセスに弱い
- データロスを招く
- 一つのカタログ構成に対して一つのファイルシステムしか使えない
- 組み合わせて使う場合は、それぞれでの構成が必要
- テーブル一覧の問い合わせ = ファイルリストの取得のため遅い
- カタログからテーブルを削除する方法がない
ユースケース
- はじめの一歩な人向け
Hive Catalog
-
Hive Metastore
に最新のMetadata file
へのパスのマッピングを記録する方式
メリット
-
Hive
で提供されるツールセットをそのまま使える
デメリット
-
Hive Metastore
サービスを起動しておく必要がある-
Amazon EMR
のような外部サービスに頼るのであれば回避可能
-
- 並行的なトランザクションが未サポート
- ACIDが担保できない
ユースケース
- すでに
Hive Metastore
を使ってる人向け
AWS Glue Catalog
Metadata file
へのパスのマッピングの記録をAWS Glue
に丸投げする方式
メリット
-
AWS Glue
がマネージドサービスであること - ほかの
AWS
のサービスとの統合が行いやすいこと
デメリット
- マルチテーブル/並行的なトランザクションが未サポート
- ACIDが担保できない
- 構成が複雑になるゆえデプロイがメンドくなる
ユースケース
-
AWS
のサービスを組み合わせて使いまっくってる人向け
Nessie Catalog
メリット
-
git
ライクな使い心地-
Nessie
でバージョン管理してくれる
-
- マルチテーブル/並行的なトランザクションに対応している
デメリット
- カタログとして
Nessie
をサポートするツールが出揃ってない-
Spark
,Flink
,Dremio
,Presto
,PyIceberg
はサポートしてる
-
-
Nessie
サービスを起動しておく必要がある-
Dremio
はマネージドサービスを提供している
-
ユースケース
- マルチテーブルや並行的なトランザクションが必要なら第一候補
REST Catalog
- 提供される
REST API
を介してMetadata file
へのパスのマッピングを記録する方式
メリット
- 他のカタログと比較してデプロイや運用が楽
- 柔軟性が高い
- マルチテーブル/並行的なトランザクションに対応している
- クラウドベンダロックインの最小化
デメリット
-
REST
クライアントが必要 - カタログとして
Nessie
をサポートするツールが出揃ってない-
Spark
,Trino
,PyIceberg
,Snowflake
はサポートしてる
-
ユースケース
- 柔軟性を求めてる人向け
JDBC Catalog
-
JDBC
を経由してRDB
にMetadata file
へのパスのマッピングを記録する方式
メリット
- 始めるのが簡単
デメリット
- マルチテーブル/並行的なトランザクションが未サポート
ユースケース
-
Java
使ってる人向け
これは誤字ですか?
OLTPとOLAPの同時十個y馬リソースの取り合いとなる
10章 Production Use
メタデータテーブル
- 各種メタデータのファイルの情報をもとに作られるテーブル
*PostgreSQL
のinformation_schema
のようなもの -
SELECT
文で問い合わせできる- クエリエンジンごとにスキーマ名が異なることに注意
履歴 (history)
- スキーマ進化に伴うスナップショットの作成履歴が追跡可能
- 入れ子集合モデル(
Nested Set Model
)で構成されている- 一つ前のスナップショット(
parent_id
)をもつ
- 一つ前のスナップショット(
ログ (metadata_log_entries)
- 最新のメタデータを保持するテーブル
- latest_snapshot_id
- latest_schema_id
- latest_sequence_number
スナップショット (snapshot)
- スナップショットのマニフェスト情報を保持するテーブル
- operation
- 行われた操作(
APPEND
,OVERWRITE
など)
- 行われた操作(
- manifest_list
-
Manifest List
のパス
-
- summary
- 統計情報 (追加件数等)
- operation
- スナップショットの作成履歴が追跡可能
-
history
同様、parent_id
をもっている
-
ファイル (files)
- 最新のスナップショットの
Data File
に関する情報を保持するテーブル- パス、パーティション条件、統計情報 (最大・最小値、NULL件数等)
マニフェスト (manifests)
- 最新のスナップショットの
Manifest File
の情報を保持するテーブル- パス、パーティションレベルの統計情報(パーティション境界)
パーティション (partitions)
- パーティション条件や
MOR
の差分件数を保持するテーブル
全データ(all_data_files)
- 全スナップショットのデータファイル情報を保持するテーブル
- 内容は
files
と大体同じ
全マニフェスト (all_manifest_files)
- 全スナップショットのマニフェストファイル情報を保持するテーブル
- 内容は
manifests
と大体同じ
参照 (refs)
- スナップショット付与された別名を保持するテーブル
- 命名方法には
BRANCH
とTAG
の2つがある- BRANCH
-
git branch
のイメージ
-
- TAG
-
git tag
のイメージ
-
- BRANCH
エントリ (entries)
- 最新のスナップショットのデータファイル(削除ファイル含む)の要約
-
files
との使い分けはよくわからん
メタデータテーブルのユースケース
スナップショットに適用された追加ファイルの履歴
SELECT f.*, e.snapshot_id
FROM catalog.table.entries AS e
JOIN catalog.table.files AS f
ON e.data_file.file_path = f.file_path
WHERE e.status = 1 AND e.snapshot_id = <your_snapshot_id>
特定のデータファイルのライフサイクルの要約
SELECT
e.snapshot_id, e.sequence_number, e.status,
m.added_snapshot_id, m.deleted_data_files_count, m.added_data_files_count
FROM catalog.table.entries AS e
JOIN catalog.table.manifests AS m
ON e.snapshot_id = m.added_snapshot_id
WHERE e.data_file.file_path = '<your_file_path>'
ORDER BY e.sequence_number ASC
パーティションの成長履歴
SELECT
e.snapshot_id, f.partition,
COUNT(*) AS files_added
FROM catalog.table.entries AS e
JOIN catalog.entries.files AS f
ON e.data_file.file_path = f.file_path
WHERE e.status = 1
GROUP BY e.snapshot_id, f.partition;
特定のブランチの変更履歴
SELECT r.name as branch_name, f.*
FROM catalog.table.refs AS r
JOIN catalog.table.entries AS e
ON r.snapshot_id = e.snapshot_id
JOIN catalog.table.files AS f
ON e.data_file.file_path = f.file_path
WHERE r.type = 'BRANCH' AND r.name = '<your_branch_name>'
ブランチの比較
- 長いから省略
各ブランチの成長履歴
SELECT
r.name as branch_name, e.snapshot_id,
SUM(f.file_size_in_bytes) as total_size_in_bytes
FROM catalog.table.refs AS r
JOIN catalog.table.entries AS e
ON r.snapshot_id = e.snapshot_id
JOIN catalog.table.files AS f
ON e.data_file.file_path = f.file_path
WHERE r.type = 'BRANCH'
GROUP BY r.name, e.snapshot_id
ORDER BY r.name, e.snapshot_id
ブランチ
-
git
風にスナップショットをブランチ管理できる - ブランチごとに別の人生を歩ませることもできる
-
refs
メタデータテーブルで追跡可能
テーブルレベルブランチ
- テーブル単位でブランチを作成する
- メリット
- 細やかな粒度での制御が可能
- デメリット
- 個々のテーブルに対して作らなきゃなのでダルイ
カタログレベルブランチ
-
Nessie
がサポート - 複数のテーブルを一括してブランチを作成する
- メリット
- まとめて作れるので楽ちん
- デメリット
- 小規模ではやりすぎ感ある
タグ
-
git
風にスナップショットにタグを付与して管理できる - ブランチ同様、テーブルレベルとカタログレベルのいずれかで作成する
-
refs
メタデータテーブルで追跡可能
トランザクション
- トランザクションをサポートするカタログで実行可能
- 機能は一般的な
RDB
同様アトミックな操作を実現するもの- カタログレベルは
Nessie
がサポート
- カタログレベルは
-
RDB
とは異なり以下の機能も有する- 特定のテーブルのみのロールバック
- 特定のテーブルを特定日時までロールバック
11章 Data Stream
ストリームデータ
- ログファイル
- センサーデータ
- SNSフィード
- 金融取引
- etc
ストリーム処理にIcebergを用いるメリット
- スケーラビリティと性能
- スキーマ進化
- ストリーム処理に割り込むことなくスキーマの更新が可能
- 信頼性
- スナップショットの分離性により、同時実行でも整合性を保つ
- Time Travel
- 前のバージョンに戻すことが容易
Apache Spark
Spark Structure Streamingの特徴
- 耐障害性
- Integration
- Spark componentとシームレスに結合できる
- MLlib, Spark SQLなど
- Spark componentとシームレスに結合できる
- リアルタイム処理
- バッチとは独立して処理される
- ストリームデータの処理結果をバッチとして流す
- ウインドウ操作のサポート
- 移動平均などの計算等
- 高スループット
- マルチデータソース
- Kafka, Flume, Kinesisなどからのストリームデータをサポート
- マイクロバッチ
- 他のストリームエンジンとは独立して動く
- マイクロバッチ単位で耐障害性を担保
- レイテンシーとスループットはトレードオフ
SparkとIcebergの連携
- DataSourceV2 APIで対応
- Sparkのデータフレームの読み書き互換性を保証
-
DataStreamWriter
でIceberg
にデータを送る- appendモード
- マイクロバッチの結果を
iceberg
のテーブルに追記する
- マイクロバッチの結果を
- completeモード
- マイクロバッチの結果で
iceberg
のテーブルを置き換える
- マイクロバッチの結果で
- appendモード
-
fanout-enabled
オプションを有効化することで、パーティションのソートをバイパスする- レイテンシーの低減
- メタデータが爆速で大量に作成されるためチューニングが必要
- コミット粒度
- 古いスナップショットの無効化
- データファイルのコンパクション
- マニフェストの最適化
- 意識すべきこと
- スキーマの整合性
- 不要なデータは投入前にフィルタリングしておく
- ジョブが死んでいないかどうかのモニタリング
Apache Flink
特徴
- ストリームバッチ処理エンジン
- イベント時処理
- 金融取引のような順序に依存する処理を可能にする
- バラバラに流れてきていても
- 金融取引のような順序に依存する処理を可能にする
- 耐障害性
- checkpoint
- savepoint
- バックプレッシャー
- 高スループット・低レイテンシー
- ウインドウ処理
- 時間ベース、件数、セッション単位でウインドウを作れる
- パターンベースでのウインドウ作成も可能
- Integration
- 種々のデータソースの入力を統合可能
- Kafka, HDFS, Cassandraなど
- 種々のデータソースの入力を統合可能
- ワンショット処理
FlinkとIcebergの連携
- DataStream/Table APIでサポート
- DataStream API
- 連続データを取り扱うAPI
- 低レイヤーAPI
- Table API
- バッチデータをテーブルとして扱うAPI
- 高レイヤーAPI
- DataStream API
Apache Kafka Connect
特徴
- 高スループット
- 耐障害性 (fault tolerance)
- リアルタイム連携
- Pub/Subなので
- 耐久性 (Durability)
- 確実にデータが届く
- ワンショット処理
KafkaとIcebergの連携
- Apache Iceberg Sink Connectorでサポート
- コミット粒度の調整
- ワンショット実行
- 複数のテーブルへの一括出力(fan-out)
- テーブル行パッチ (update/delete/upsert)
設定
- 公式ドキュメントに記載された内容との食い違いが大きい模様
- 素直に公式ドキュメント見た方が良さげ
AWS
-
公式ドキュメントとの食い違いが大きい模様
-
素直に公式ドキュメント見た方が良さげ
-
Amazon Athena
-
Amazon EMR
-
Amazon Data Firehose
-
Amazon Redshift
12章 Governance and Security
セキュリティに関する検討事項
- ユースケース
- 社外秘なデータはカタログレベルセキュリティ
- そこまで強くなければファイルレベルセキュリティ
- スケーラビリティ
- データが多くなり出すとファイルレベルセキュリティはスケーラビリティが低下する
- 性能
- セマンティックレイヤは性能の向上に寄与する
- だがしかし導入は大変
- データ抽象化
- 余計なものは載っけない
- オペレーション
- 煩雑な操作を要すると使われなくなる
- 適材適所で
- 冗長性とフェイルオーバー
- 可用性と信頼性を担保しているかどうか
Data Fileのセキュリティ
ファイルストレージ
-
ストレージレベルでのセキュリティ担保が最重要
- 特権アクセスの最小化
- アクセスは特定のタスクのみに制限
- ファイルパーミッションを最小限に
- 暗号化
- ストレージプラットフォームで提供される暗号化の有効化
- 強固な認証
- MFA (Multi-factor Authentication)の有効化
- 監査ログ
- ストレージプラットフォームで提供される監査ログの有効化
- ライフサイクル管理
- 不要なファイルの削除・アーカイブ
- モニタリング
- アラートシステム等によるモニタリング
- 特権アクセスの最小化
-
メリット
- 細粒度での制御が可能
-
デメリット
- ファイルファ増え出すと管理が煩雑化する
- スケーラビリティの低下
HDFS
- ACL (Accexx Control list)
- 暗号化
- 透過的暗号化 (transparent data encryption)
- ディスクのデータブロックレベルでの暗号化
- 暗号化ゾーン
- ファイル・フォルダの書き込みで暗号化
- ファイル・フォルダからの読み出しで復号化
- https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/TransparentEncryption.html
- 透過的暗号化 (transparent data encryption)
- パーミッション
- ユーザ / ユーザグループレベルでのパーミッションの変更
- https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsPermissionsGuide.html
Amazon S3
- 使用例がメインだったのでリンクを貼るだけにとどめる
- 暗号化
- バケットポリシー
- IAM
- ACL
Azure Data Lake Storage
- 使用例がメインだったのでリンクを貼るだけにとどめる(Azureよくわからん)
- https://learn.microsoft.com/ja-jp/azure/storage/blobs/security-recommendations
- https://learn.microsoft.com/ja-jp/azure/storage/common/storage-service-encryption?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json&bc=%2Fazure%2Fstorage%2Fblobs%2Fbreadcrumb%2Ftoc.json
- https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/management/overview
Google Cloud Storage
- 使用例がメインだったのでリンクを貼るだけにとどめる
セマンティックレイヤーのセキュリティ
- セマンティックレイヤー
- 仮想的な抽象層
- 構造化されたビジネスフレンドリなビュー
- 事前に計算しておくことでスループットの改善
- 集中管理によるセキュリティの担保
- 仮想的な抽象層
- 検討事項
- ラベルやタグ付けによるファイルの分類
- ACLポリシーの定義
- マスキングルールの実装
- 世代管理
- ルールの文書化
Dremio
- Dremioのセマンティックレイヤー
Trino
-
分散クエリエンジン
-
公式サイト漁ってもセマンティックレイヤーの話が見つからない
-
セキュリティモード
- DEFINER
- ビューオーナーの権限でアクセス(デフォルト)
- INVOKER
- 実行ユーザの権限でアクセス
- https://trino.io/docs/current/sql/create-view.html#security
-
PostgreSQL
のCREATE FUNCTION
のDEFINER/INVOKER
をVIEW
に適用した感じかな
- DEFINER
-
ロールベースアクセス制御(RBAC)
- 公式サイト漁っても
RBAC
に関する話見つからない - 代わりに
CREATE ROLE
のリンク
- 公式サイト漁っても
カタログレベルのセキュリティ
- メリット
- カタログによる集中管理
- 細粒度のアクセス制御
- データアクセスの単純化
- カタログがファイル構造を抽象化しているため
- デメリット
- アクセス制御がメタデータに張り付くためスループットの低下を招く
Nessie
-
Nessie
はパスとメタデータのみを管理- 直接的にデータを格納してはいない
- アクセス制御はメタデータ、およびメタデータが保持するパスのみ
- データファイル自身は守らない
- ファイルレベルのセキュリティは別途検討が必要
- 認可ルールは
Common Expression Language
(CEL)を使用して定義する - Common Expression Language
Tabular
- クラウドネイティブな
headless-warehouse
- クエリエンジンを持たない
- アクセス制御フレームワーク
- ロールにアクセス特権を割り当てるモデル
- 今は
databrics
とくっついた -
Iceberg
視点ではデータファイルとカタログを集中管理する場
AWS Glue
-
AWS Lake Formation
を経由してセキュリティ機構を組み立てる- タグベースのアクセス制御
13章 Migrationg to Iceberg
マイグレーションの検討事項
- Icebergのデータ構造への適合
- ときには再構成が必要になることも
- Icebergの
list
,struct
,map
を使っていい感じに
- Icebergの
- ときには再構成が必要になることも
- パイプラインへの適合
- ときには
ETL
の変更が必要になることも- Icebergは多くのユーティリティを用意している
- ときには
- ワークフローへの適合
- Icebergをワークフローに組み込む上でデータ依存やスケジュール、データアクセスの変更を伴うことも
- 実行中のジョブを全て片付けておくことが肝要
マイグレーション方法
In-place
-
クエリエンジンを通さず、移行元のファイルを直コピー
-
低リソース向け
-
メリット
- とにかく単純
- コスト低め
-
デメリット
- リスキー
- マイグレーション後のロールバックが簡単ではない
- クエリを通さず直接ファイルをコピーするためIDのケアが必要になるかも
Shadow
-
クエリエンジンを通して、データを移行する
- CTAS (Create Tabke As Select, Copy Toなど)
-
メリット
- とにかく安全
- 驚き最小
-
デメリット
- 複雑になりがち
- コスト高め
Shadowマイグレーションの手順
Hiveからの移行
2つの方法が提供されている
-
snapshot
- 移行元の構造のまま、Iceberg上にスナップショットを作る
- メタデータだけを作る
- 移行中も元データへのアクセスは可能
- 全てのメタデータの作成が完了したら、ファイルの指し先を変える
- 移行元の構造のまま、Iceberg上にスナップショットを作る
-
migrate
- スキーマやパーティション情報のメタデータを移行しつつ、ファイルの指し先も変える
- 移行元はリンクを切る
- 移行元に書いて、移行先から読むような運用が求められる
- スキーマやパーティション情報のメタデータを移行しつつ、ファイルの指し先も変える
-
わかりやすそうな解説
Delta Lakeからの移行
iceberg-delta-lake
モジュールのDeltaLakeToIcebergMigrationActionsProvider
を使う
Hudiからの移行
iceberg-hudi
モジュールのHudiTo IcebergMigrationActionsProvider
を使う
管理外のファイルの移行
add_files
手続きを使う
クエリによる移行
CTAS
-
移行先にテーブルが存在しない場合
-
メリット
- スキーマ進化の維持
- ロールバックも可能
- パーティションのコントロール
- 新たラバーてょん条件に差し替えることも可能
- コード体系のりマッピングも容易
- スキーマ進化の維持
-
検討事項
- 大規模な場合はインクリメンタルな移行の検討が必要
- 初回はCTAS, 以降はINSERT INTO SELECT
- パラレル実行させることで時短になる
- モニタリングはしっかりと
- 大規模な場合はインクリメンタルな移行の検討が必要
COPY INTO
-
移行先にテーブルが存在する場合
-
メリット
- スキーマが存在しないデータ(CSVなど)の場合に採用する
- オプションでインクリメンタルな移行を行わせることもできる
-
検討事項
- 移行元がスキーマレスゆえ、データの品質(型が違うとか)に問題ないか確認する
- NULL値のハンドリング
INSERT INTO SELECT
- 移行先にテーブルが存在する場合
14章 Real-Workd Usecase
WAP (Weite-Audit-Publish)パターン
- データ品質を高く保つことは重要
- 妥協すると後工程に悪い影響を与える
- (Write) データをソースチャンネルから抽出し、テンポラリに書き出す
- (Audit) テンポラリ内で、Null値、重複値などを省く
- (Publish) prod環境に発行する
BIダッシュボード
- データが大規模になるにつれて、性能が悪化の一途をたどりがち
- BIデータ抽出
- キューブ計算
- 多次元の集約計算
- 常に新鮮なデータで再作成する必要がある
- 大規模ゆえ、時には
OOM
に陥ることも - 履歴データの蓄積がコストの増大とメンテナンスを難解に
- 結果、利用者は技術者にデータ構造の改善依頼が必要となる
Aggregate reflection
- 事前計算の結果を
Iceberg
のテーブルに書くに右する機能。- マテビューっぽい感じか?
- メリット
- クエリエンジンが自動的に構造を調整する
- クエリエンジンがいい感じに
OOM
の回避を試みる - クエリエンジンが履歴データの自動的なクリーンアップ
- ダッシュボードは元のテーブルで構築するが、参照時にエリエンジンがいい感じに差し替える
- 元のテーブルも
Iceberg
のテーブルなら、データの更新を追跡する
CDC (Change Data Capture)
- 下層の最新のデータとの同期を効果的に行うもの
- バッチ処理ではバルク単位でデータのやり取りを行うため、リアルタイム性が乏しい
- 明細テーブル、サマリーテーブル、変更ログテーブルを用意する
- 明細テーブルを変更したら、ログを変更ログテーブルに追記する
- 変更ログテーブルの差分を元にサマリーテーブルを更新する