LabHub
开始
学习 学习路径 课程

湖仓表格式 — 从元数据理解 Apache Iceberg

把按月分区的表改成按天 — 旧文件保持不动

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

목표

원천 열(order_ts)에 변환 규칙만 걸어 나누는 숨은 파티셔닝을 만들고, 조건 하나가 몇 개 파일·몇 행을 열게 되는지 계획으로 잰다. 표를 쓰는 도중에 달 단위를 날 단위로 바꾸고(파티션 진화), 옛 파일은 옛 규칙 그대로 둔 채 새 파일만 새 규칙을 따르는 것을 metadata 로 확인한다.

왜 중요한가

Hive 식 표는 파티션을 로 만든다. order_date 같은 열을 따로 두고, 쓰는 사람도 읽는 사람도 그 열을 알아야 한다. 읽는 쪽이 order_ts 로만 걸면 파티션을 하나도 건너뛰지 못하고, 쓰는 쪽이 시간대를 잘못 계산하면 행이 엉뚱한 파티션에 들어간다. 그리고 파티션 방식을 바꾸려면 표 전체를 다시 써야 한다. Iceberg 는 파티션을 규칙으로 둔다. days(order_ts) 처럼 원천 열과 변환만 적어 두면 엔진이 파일마다 파티션 값을 계산해 매니페스트에 적고, 읽는 쪽은 order_ts 조건만으로 파일을 건너뛴다. 규칙은 스펙 ID 가 붙어 metadata 에 쌓이므로, 규칙을 바꿔도 옛 파일은 옛 스펙으로 계속 읽힌다. 다시 써야 할 것 같다는 느낌이 가장 흔한 오해다.

단계

  1. /root/ice/part/month.py(앱 ice-part-month)로 lake.part.ordersPARTITIONED BY (months(order_ts)) 로 만들고 3월 한 달(31개 파일)을 한 번에 커밋하세요.
  2. /root/ice/part/plan1.py(pyiceberg)로 order_ts 가 2026-03-10 하루인 조건의 계획을 세워 /root/ice/part/out/plan_march.json 에 쓰세요.
  3. /root/ice/part/evolve.py(앱 ice-part-evolve)로 months(order_ts)days(order_ts) 로 바꾸세요.
  4. /root/ice/part/april.py(앱 ice-part-april)로 4월 한 달(30개 파일)을 한 번에 커밋하세요.
  5. /root/ice/part/plan2.py 로 3월 10일과 4월 10일 조건의 계획을 세워 /root/ice/part/out/plan.json 에 쓰세요.
  6. /root/ice/part/bucket.py(앱 ice-part-bucket)로 lake.part.customersPARTITIONED BY (bucket(4, customer_id)) 로 만들고 고객을 넣으세요.
  7. /root/ice/part/specs.pylake.part.orders 의 기본 스펙 ID 와 스펙별 데이터 파일 수를 /root/ice/part/out/specs.json 에 쓰세요.
  8. /root/ice/part/report.md## 숨은 파티셔닝 ## 파티션 진화 ## 버킷 세 절을 쓰세요.

참고

달로 나눈 표 — 파티션 열 없이

/root/ice/part/month.py 를 앱 이름 ice-part-month 로 만들어 lake.part.orders(열 여섯 개, 'format-version' = '2')를 PARTITIONED BY (months(order_ts)) 로 만들고 /data/ice/orders/2026-03-*.csv 31개를 한 번의 append() 로 넣으세요.

months(order_ts) 는 1970년 1월부터 센 달 수를 파티션 값으로 씁니다. 스키마에 새 열이 생기지 않는다는 점을 확인해 보세요. 채점기는 스펙 0 의 변환이 month 인지, 첫 커밋이 3월 전체인지, 파일들의 파티션 값이 모두 2026년 3월인지 봅니다.

하루 조건이 여는 파일 — 달 단위의 한계

/root/ice/part/plan1.py(pyiceberg)로 order_ts >= 2026-03-10T00:00:00+00:00 이고 < 2026-03-11T00:00:00+00:00 인 조건의 스캔을 만들어, 계획된 파일 수·그 파일들의 record_count 합·실제로 걸리는 행 수를 /root/ice/part/out/plan_march.json{"files_planned", "records_scanned", "rows"} 로 쓰세요(지금 표에는 3월만 있습니다).

조건은 order_ts 로만 걸었는데도 파티션 값(달)과 비교되어 다른 달의 파일은 빠집니다. 그런데 3월 10일 하루를 원해도 3월 파일은 한 달 치를 통째로 읽어야 합니다. records_scanned 와 rows 의 차이가 그 비용입니다. 채점기는 첫 스냅샷(3월만 있던 때) 기준으로 같은 계획을 다시 세워 견줍니다.

파티션 진화 — metadata 만 바뀐다

/root/ice/part/evolve.py 를 앱 이름 ice-part-evolve 로 만들어 ALTER TABLE lake.part.orders REPLACE PARTITION FIELD months(order_ts) WITH days(order_ts) 를 돌리세요.

스펙 1 이 새로 생기고 기본(default-spec-id)이 1 로 바뀝니다. 스냅샷은 생기지 않고 데이터 파일도 그대로입니다 — 앞으로 쓰는 파일만 새 규칙을 따릅니다. 채점기는 스펙 목록·기본 스펙·스냅샷 수를 봅니다.

4월 커밋 — 새 파일만 새 스펙

/root/ice/part/april.py 를 앱 이름 ice-part-april 로 만들어 /data/ice/orders/2026-04-*.csv 30개를 한 번의 append() 로 넣으세요. 3월 파일은 다시 쓰지 마세요.

새 커밋의 파일은 spec_id 1 로, 날마다 따로 적힙니다. 3월 파일은 spec_id 0(달) 그대로 같은 스냅샷 안에 함께 삽니다. 읽는 엔진은 스펙마다 따로 계획을 세우므로 두 규칙이 섞여 있어도 결과는 같습니다. 채점기는 3월 파일이 첫 커밋의 경로·스펙 그대로인지도 봅니다.

같은 하루 조건, 다른 비용

/root/ice/part/plan2.py 로 3월 10일 하루와 4월 10일 하루 조건의 계획을 각각 세워 /root/ice/part/out/plan.json{"march": {"files_planned", "records_scanned", "rows"}, "april": {…}} 로 쓰세요.

두 날은 행 수가 비슷한데 읽어야 할 행 수는 크게 다릅니다. 3월은 달 파일을 통째로, 4월은 그날 파일 하나만 엽니다. 채점기는 지금 표로 같은 계획을 다시 세워 견주고, 4월 쪽이 그날 행만 읽는지 봅니다.

가짓수가 많은 열은 버킷으로

/root/ice/part/bucket.py 를 앱 이름 ice-part-bucket 으로 만들어 lake.part.customers(customer_id STRING, tier STRING, region STRING, signup_date DATE)PARTITIONED BY (bucket(4, customer_id)) 로 만들고 /data/ice/customers.csv 를 넣으세요.

bucket(N, 열) 은 값의 32비트 murmur3 해시를 N 으로 나눈 나머지를 파티션 값으로 씁니다. 스펙이 정한 해시라 어느 엔진이 계산해도 같은 칸이 나옵니다 — 채점기는 pyiceberg 로 고객마다 칸을 다시 계산해 파일의 파티션 값과 견줍니다.

한 표 안의 두 규칙

/root/ice/part/specs.py(pyiceberg)로 lake.part.orders 의 기본 스펙 ID 와 스펙별 데이터 파일 수를 /root/ice/part/out/specs.json{"default_spec_id": 정수, "files_by_spec": {"0": 정수, "1": 정수}} 로 쓰세요.

tbl.inspect.files() 의 spec_id 열로 셉니다(content 0 이 데이터 파일). 한 스냅샷 안에 두 스펙의 파일이 섞여 있는 것이 정상입니다.

파티션 설계를 팀 규칙으로

/root/ice/part/report.md## 숨은 파티셔닝 ## 파티션 진화 ## 버킷 세 절을 쓰세요. 둘째 절에는 5단계의 3월·4월 records_scanned 두 값을 숫자로 넣으세요.

처음에 달로 나눈 선택이 틀렸던 것일까요, 아니면 자료가 늘어 맞지 않게 된 것일까요. 옛 3월 파일을 언젠가 다시 써야 한다면 그 이유는 무엇이어야 하는지도 적어 보세요.