Iceberg์ ์ฃผ์ ๊ธฐ๋ฅ์ ์๊ฐํ๊ณ Delta-lake, Hudi์ ๋น๊ตํ์ฌ ์๊ฐํฉ๋๋ค.
Spark ์คํ ์์
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("Jupyter").getOrCreate()
spark
-- ํ
์ด๋ธ ์์ฑ
CREATE DATABASE IF NOT EXISTS nyc
๋ฐ์ดํฐ ๋ก๋ ๋ฐ ํ ์ด๋ธ ์์ฑ
df = spark.read.parquet("/home/iceberg/data/yellow_tripdata_2021-04.parquet")
df.write.saveAsTable("nyc.taxis")
PySpark๋ฅผ ์ฌ์ฉํ ํ ์ด๋ธ ๋ฐ์ดํฐ ํ์ธ
df.show(n=10, truncate=False, vertical=True)
๐ Iceberg์ ์ฃผ์ ๊ธฐ๋ฅ
1. โ ์คํค๋ง ์งํ(Schema Evolution)
Iceberg๋ ๊ธฐ์กด ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ๋ ํ ์ด๋ธ์ ์คํค๋ง๋ฅผ ์ ์ฐํ๊ฒ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
- ์ปฌ๋ผ ์ถ๊ฐ, ์ด๋ฆ ๋ณ๊ฒฝ, ์์ ๋ณ๊ฒฝ์ด ๋ชจ๋ ์์ ํ๊ฒ ๊ฐ๋ฅ
- ๋ด๋ถ์ ์ผ๋ก field ID๋ฅผ ์ฌ์ฉํด, ์์์ ๋ฌด๊ดํ๊ฒ ๋ฐ์ดํฐ๋ฅผ ์ธ์
๐ ์์:
-- ์ปฌ๋ผ ๋ณ๊ฒฝ
ALTER TABLE nyc.taxis RENAME COLUMN fare_amount TO fare
ALTER TABLE nyc.taxis RENAME COLUMN trip_distance TO distance
-- ์ฝ๋ฉํธ ์ถ๊ฐ
ALTER TABLE nyc.taxis ALTER COLUMN distance COMMENT 'The elapsed trip distance in miles reported by the taximeter.'
-- ํ์
๋ณ๊ฒฝ
ALTER TABLE nyc.taxis ALTER COLUMN distance TYPE double;
-- ์ปฌ๋ผ์ ์์ ๋ณ๊ฒฝ: ํ
์ด๋ธ ์กฐํ ์ ํ์๋๋ ์ปฌ๋ผ์ ์์น๋ฅผ ๋ณ๊ฒฝํฉ๋๋ค. distance ๋ค์ fare ์ปฌ๋ผ์ ๋ณด์ฌ์ค๋๋ค.
ALTER TABLE nyc.taxis ALTER COLUMN distance AFTER fare;
-- ์ปฌ๋ผ ์ถ๊ฐ: ๊ธฐ์กด HDFS์ ๋ค๋ฅด๊ฒ ์ปฌ๋ผ์ ์ถ๊ฐํด๋ nulใ
ฃ ๊ฐ์ผ๋ก ์ฐ์ ์ถ๊ฐ๋ฉ๋๋ค.
ALTER TABLE nyc.taxis
ADD COLUMN fare_per_distance_unit float AFTER distance
-- ์ถ๊ฐํ ์ปฌ๋ผ์ ๊ฐ์ ์ค์ ํฉ๋๋ค.
UPDATE nyc.taxis
SET fare_per_distance_unit = fare/distance

๐ง ์ ์ค์ํ๊ฐ์?
๊ธฐ์กด Hive ํ
์ด๋ธ์ ์คํค๋ง ๋ณ๊ฒฝ ์ ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ์ฌ์์ฑํ๊ฑฐ๋ ๋ถ์์ ํ ๋์์ ์ ๋ฐํ ์ ์์ง๋ง,
Iceberg๋ ๋ช
์์ ๋ฉํ๋ฐ์ดํฐ ๊ด๋ฆฌ๋ก ๋ฐ์ดํฐ ์ ํฉ์ฑ์ ์ ์งํ๋ฉฐ ์คํค๋ง ๋ณ๊ฒฝ์ ์ง์ํฉ๋๋ค.
2. ๐งญ Time Travel
Iceberg๋ ์ด์ ์์ ์ ๋ฐ์ดํฐ๋ฅผ ๊ทธ๋๋ก ์กฐํํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
๋ชจ๋ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ์ค๋
์ท ๋จ์๋ก ๊ธฐ๋ก๋๋ฉฐ, ํน์ snapshot ID ๋๋ timestamp๋ก ์ด์ ์ํ๋ฅผ ์กฐํํ ์ ์์ต๋๋ค.
๐ ์์:
-- ํ
์ด๋ธ์ ํ์คํ ๋ฆฌ ์กฐํ
SELECT * FROM nyc.taxis.history

original_snapshot = df.head().snapshot_id
spark.sql(f"CALL system.rollback_to_snapshot('nyc.taxis', {original_snapshot})")
original_snapshot
์๋ณธ Snapshot id(259~)๋ก ์๋ณตํ๊ณ ๋ฐ์ดํฐ๋ฅผ ํ์ธํด๋ณด๋ฉด fare_per_distance_unit ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
๐ Iceberg Snapshot์ด ์์ฑ๋๋ ์กฐ๊ฑด์?
- ํ
์ด๋ธ์ ๋ฐ์ดํฐ ๋ณ๊ฒฝ(์ฝ์
, ์์ , ์ญ์ )์ด ๋ฐ์ํ ๋๋ง๋ค ์๋ก์ด ์ค๋
์ท์ด ์์ฑ๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด, ํ ์ด๋ธ์ ์๋ก์ด ํ์ ์ถ๊ฐํ๊ฑฐ๋ ๊ธฐ์กด ๋ฐ์ดํฐ๋ฅผ ์์ ๋๋ ์ญ์ ํ๋ DML ์์ ์ด ์คํ๋๋ฉด Iceberg๋ ์๋์ผ๋ก ์๋ก์ด ์ค๋ ์ท์ ๋ง๋ค์ด ํด๋น ์์ ์ ํ ์ด๋ธ ์ํ๋ฅผ ๊ธฐ๋กํฉ๋๋ค. - ์ค๋
์ท์ Iceberg์ commit ์์
์ด ๋ฐ์ํ ๋๋ง๋ค ์์ฑ๋ฉ๋๋ค.
๋ฐ์ดํฐ๊ฐ ํ ์ด๋ธ์ ๋ฐ์๋๋ commit ์์ ๋ง๋ค ํ ์ด๋ธ์ ์ ์ฒด ์ํ๋ฅผ ๋ํ๋ด๋ ์ค๋ ์ท์ด ๋ง๋ค์ด์ง๋๋ค. ์ด commit์๋ ๋จ์ํ ๋ฐ์ดํฐ ์ฝ์ ๋ฟ ์๋๋ผ, overwrite, delete, update ๋ฑ ๋ชจ๋ ๋ฐ์ดํฐ ๋ณ๊ฒฝ ์์ ์ด ํฌํจ๋ฉ๋๋ค. - ์ค๋
์ท์ ํ
์ด๋ธ ๋ฉํ๋ฐ์ดํฐ์ ๋ณ๊ฒฝ(์: ์คํค๋ง ๋ณ๊ฒฝ, ํํฐ์
๋ณ๊ฒฝ)์๋ ์์ฑ๋ ์ ์์ต๋๋ค.
์คํค๋ง ๋ณ๊ฒฝ์ด๋ ํํฐ์ ๊ตฌ์กฐ ๋ณ๊ฒฝ ๋ฑ ํ ์ด๋ธ ๊ตฌ์กฐ์ ์ํฅ์ ์ฃผ๋ ์์ ๋ ์๋ก์ด ์ค๋ ์ท์ ์์ฑํ๋ ํธ๋ฆฌ๊ฑฐ๊ฐ ๋ฉ๋๋ค(์ผ๋ฐ์ ์ผ๋ก ๋ฉํ๋ฐ์ดํฐ commit์ด ๋ฐ์ํ๋ ๊ฒฝ์ฐ).
๐ง ํ์ฉ ์์
- ์๋ชป๋ ์ ๋ฐ์ดํธ ๋ณต๊ตฌ
- ํ์คํ ๋ฆฌ ๋น๊ต
- ์์ ๊ธฐ๋ฐ ๋ถ์ (๊ณผ๊ฑฐ ์ํ ๋ถ์)
3. ๐ ์๋ ํํฐ์ ๋ (Hidden Partitioning)
Iceberg๋ ์ฌ์ฉ์๊ฐ ์ง์ ํํฐ์ ๋ ๋๋ ํ ๋ฆฌ๋ฅผ ์ ๊ฒฝ ์ฐ์ง ์์๋ ๋๋๋ก ์ค๊ณ๋์์ต๋๋ค. ํํฐ์ ์ ํ ์ด๋ธ ์ ์์๋ง ์ ์ธํ๋ฉด ๋ด๋ถ์ ์ผ๋ก ์๋์ผ๋ก ํํฐ์ ๋๋ ํ ๋ฆฌ๋ฅผ ๊ด๋ฆฌํด์ค๋๋ค.
๐ ์์:
ALTER TABLE nyc.taxis
ADD PARTITION FIELD VendorID
๐ง ์ฅ์
- ์ฌ์ฉ์๋ ํํฐ์ ๋์ ์์ํ์ง ์๊ณ SQL๋ง์ผ๋ก ์์ ๊ฐ๋ฅ
- ๋ณต์กํ ๋๋ ํ ๋ฆฌ ์ค๊ณ ์์ด๋ ์ฟผ๋ฆฌ ์ฑ๋ฅ ์ต์ ํ ๊ฐ๋ฅ
- ํํฐ์ ์ปฌ๋ผ์ด ๋ณ๊ฒฝ๋์ด๋ ์ด์ ํํฐ์ ์ด ๋ฌดํจํ๋์ง ์์
4. ๐ ACID ํธ๋์ญ์ ์๋ฒฝ ์ง์
Iceberg๋ ๋ชจ๋ ๋ฐ์ดํฐ ์กฐ์์ ์ค๋ ์ท ๊ธฐ๋ฐ์ ํธ๋์ญ์ ๋จ์๋ก ์ฒ๋ฆฌํฉ๋๋ค. ์ฌ๋ฌ ์์ ์ด ๋์์ ์ด๋ฃจ์ด์ ธ๋ ์ถฉ๋ ์์ด ์์ ํ๊ฒ ๋ณํฉ๋ฉ๋๋ค.
๐ง ์ค๋ฌด์์ ์ค์ํ ์ด์
- ๋ฐฐ์น & ์คํธ๋ฆฌ๋ฐ ํ์ดํ๋ผ์ธ์ ๋์์ ์ด์ํ ๋ ์ถฉ๋ ์์
- Spark, Flink, Trino ๋ฑ ๋ค์ํ ์์ง์์ ์์ ํ๊ฒ ๋ณ๋ ฌ ์์ ๊ฐ๋ฅ
5. ๐งฑ ์ค๋ ์ท(Snapshot) ๊ธฐ๋ฐ ๋ฉํ๋ฐ์ดํฐ ๊ด๋ฆฌ
Iceberg๋ ๋ณ๊ฒฝ์ด ์ผ์ด๋ ๋๋ง๋ค ์ค๋ ์ท์ ์์ฑํ๊ณ , ๋ชจ๋ ํ ์ด๋ธ์ ์ํ๋ ๋ฉํ๋ฐ์ดํฐ ํ์ผ๋ก ๊ด๋ฆฌ๋ฉ๋๋ค.
SELECT snapshot_id, manifest_list
FROM nyc.taxis.snapshots
๐ก ์ค๋ ์ท ๊ตฌ์ฑ ์์:
- metadata.json: ํ ์ด๋ธ ๊ตฌ์กฐ, ์ค๋ ์ท ๋ชฉ๋ก
- manifest list: ์ด๋ค manifest ํ์ผ์ด ํฌํจ๋์๋์ง
- manifest file: ์ด๋ค ๋ฐ์ดํฐ ํ์ผ์ด ์ด๋ค ํํฐ์ ์ ์๋์ง
๐ง ์ ์ด๊ฒ ์ค์ํ ๊น?
- ํ ์ด๋ธ์ ์ฌ์์ฑํ์ง ์๊ณ ๋ ๋ฒ์ ๋๊ณผ ๋กค๋ฐฑ ๊ฐ๋ฅ
- ํ ์ด๋ธ ์ํ๋ฅผ ๊ฒฝ๋ํ๋ ๋ฉํ๋ฐ์ดํฐ๋ก๋ง ๊ด๋ฆฌ ๊ฐ๋ฅ
- ๊ฐ์ฒด ์คํ ๋ฆฌ์ง ํ๊ฒฝ(S3, GCS ๋ฑ)์ ์ต์ ํ
6. ๐ ๋ฉํฐ ์์ง ํธํ์ฑ
Iceberg๋ ๋ค์ํ ์์ง์์ ๋์ผํ ํ ์ด๋ธ ํฌ๋งท์ ๊ณต์ ํ ์ ์๋๋ก ์ค๊ณ๋์์ต๋๋ค.
- Spark
- Trino / Presto
- Flink
- Hive (์ผ๋ถ ์ ํ์ )
๐ง ํ๋์ ํ ์ด๋ธ์ ์ฌ๋ฌ ์์ง์์ ๋ณ๋ ฌ๋ก ์ ๊ทผํ ์ ์๋ค๋ ์ ์ ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ ์ํคํ ์ฒ๋ฅผ ํจ์ฌ ์ ์ฐํ๊ฒ ๋ง๋ค์ด์ค๋๋ค.
7. ๐ ์ฟผ๋ฆฌ ์ต์ ํ ๊ธฐ๋ฅ: Pruning & Pushdown
Iceberg๋ ์ฟผ๋ฆฌ ์ฑ๋ฅ์ ๋์ด๊ธฐ ์ํ ๋ค์ํ ๊ธฐ๋ฅ์ ๋ด์ฅํ๊ณ ์์ต๋๋ค:
- Column Pruning: ํ์ํ ์ปฌ๋ผ๋ง ์ฝ์
- Partition Pruning: ์กฐ๊ฑด์ ๋ฐ๋ผ ํํฐ์ ์ค์บ ์ต์ํ
- Predicate Pushdown: ์ฟผ๋ฆฌ ์กฐ๊ฑด์ ์คํ ๋ฆฌ์ง ๋ ๋ฒจ๋ก ์ ๋ฌ
์ด๋ฌํ ์ต์ ํ๋ ๋ด๋ถ์ ํ์ผ ์์ค ๋ฉํ๋ฐ์ดํฐ ๋๋ถ์ ๊ฐ๋ฅํฉ๋๋ค.
๐ Iceberg vs Delta Lake vs Hudi ๋น๊ต
Iceberg | Delta-Lake | Hudi | |
ACID ํธ๋์ญ์ | โ | โ | โ |
Time Travel | โ | โ | ์ ํ์ |
Schema Evolution | โ (์์ ์ ) | โ | โ |
ํํฐ์ ๋ ์ถ์ํ | โ (์๋ ํํฐ์ ๋) | โ | โ |
๋ฉํฐ์์ง ์ง์ | โ (Spark, Trino, Flink ๋ฑ) | Spark ์ค์ฌ | Flink ์ค์ฌ |
์ค๋ ์ท ๋ฉํ๋ฐ์ดํฐ | โ (๋ ๋ฆฝ์ ๊ตฌ์กฐ) | ์ ํ์ | ์ ํ์ |
์ค์๊ฐ ์คํธ๋ฆฌ๋ฐ ์ ํฉ์ฑ | โ | โ | โ |