공부를 하다/Databricks

Day 10. Delta Lake 심화 — 최적화와 데이터 적재

Banaaan 2026. 8. 25. 12:36

데이터를 계속 쌓다 보면 성능이 떨어진다. 오늘은 Delta Lake 테이블을 빠르게 유지하는 방법과, 데이터를 안전하게 적재하는 패턴을 정리한다.


왜 최적화가 필요한가? — Small File Problem

데이터를 계속 적재하면 작은 파일이 쌓인다.

Delta 테이블 폴더
├── part-00001.parquet (1MB)
├── part-00002.parquet (500KB)
├── part-00003.parquet (200KB)
... 파일 수천 개

쿼리할 때 파일 수천 개를 하나씩 열어야 해서 느려진다. 이게 Small File Problem이다.


OPTIMIZE — 작은 파일 합치기

OPTIMIZE orders

흩어진 작은 파일들을 128MB짜리 큰 파일로 합친다.

Before: 파일 1000개 (각 1MB)
After:  파일 8개 (각 128MB)

ZORDER — 자주 쓰는 컬럼 기준으로 데이터 모으기

OPTIMIZE가 파일 개수를 줄인다면, ZORDER는 파일 안의 데이터 배치를 최적화한다.

OPTIMIZE orders ZORDER BY (customer_id)

WHERE customer_id = 1001 쿼리가 오면:
- ZORDER 없음: 전체 파일 스캔
- ZORDER 있음: 해당 customer_id가 모인 파일 몇 개만 스캔

단점: 새 데이터가 들어올 때마다 전체를 다시 재정렬해야 한다.

Day 1: OPTIMIZE ZORDER 실행 → 파일 10개 정렬 완료
Day 2: 새 데이터 유입 → 새 파일 50개 추가 (정렬 안 됨)
Day 2: OPTIMIZE ZORDER 다시 실행 → 기존 10개 + 새 50개 전체 재정렬

ZORDER는 전체 데이터 분포를 보고 정렬하는 알고리즘이라, 새 데이터가 끼어들면 기존 정렬이 깨져서 전부 다시 처리해야 한다.


Liquid Clustering — ZORDER의 진화 버전

ZORDER의 전체 재정렬 문제를 해결한 신규 기능(2023).

-- 테이블 생성 시 클러스터링 컬럼 지정
CREATE TABLE orders
CLUSTER BY (customer_id, order_date);

-- 이후 OPTIMIZE만 실행하면 자동 적용
OPTIMIZE orders

핵심 차이 — 점진적(incremental) 처리:

Day 1: OPTIMIZE → 파일 10개 클러스터링 완료 (완료 표시 저장)
Day 2: 새 데이터 → 새 파일 50개 추가
Day 2: OPTIMIZE → 새 파일 50개만 처리, 기존 10개는 건드리지 않음

Delta Lake가 "이 파일은 이미 클러스터링 됐음"을 기억하고 있어서 새 파일만 처리한다.

여기서 "Clustering"은 Spark 클러스터(서버 묶음)가 아니라, 비슷한 데이터를 같은 파일에 모으는 것을 의미한다.

  ZORDER Liquid Clustering
처리 방식 전체 재정렬 새 파일만 점진적 처리
컬럼 변경 전체 재정렬 필요 ALTER TABLE로 간단하게
신규 테이블 권장 X
-- 클러스터링 컬럼 변경
ALTER TABLE orders CLUSTER BY (region, order_date)

VACUUM — 오래된 파일 삭제

Delta Lake는 UPDATE/DELETE를 해도 기존 파일을 바로 삭제하지 않는다. Time Travel을 지원하려면 이전 파일이 남아있어야 하기 때문이다.

VACUUM orders

기본값으로 7일 이상 된 파일을 삭제한다. 7일치 Time Travel은 보장된다.

-- 보존 기간 직접 지정
VACUUM orders RETAIN 720 HOURS  -- 30일치 유지

주의: VACUUM 실행 후 삭제된 파일은 복구 불가능하다. 그 이전 버전으로 Time Travel도 불가능하다.


COPY INTO — 중복 없이 파일 적재

COPY INTO orders
FROM '/Workspace/Users/practice-user/data/'
FILEFORMAT = CSV
FORMAT_OPTIONS ('header' = 'true', 'inferSchema' = 'true')

핵심: 이미 적재한 파일은 자동으로 건너뛴다. 같은 명령을 10번 실행해도 데이터는 한 번만 들어간다. 이를 멱등성(idempotent) 이라고 한다.

  COPY INTO Auto Loader
방식 SQL 명령어 스트리밍
새 파일 감지 수동 실행 자동 감지
적합한 상황 배치, 소규모 대용량, 실시간

CTAS — 쿼리 결과로 테이블 만들기

CREATE OR REPLACE TABLE orders_kr
AS SELECT * FROM orders WHERE country = 'KR'

쿼리 결과가 바로 Delta 테이블이 된다. OR REPLACE를 붙이면 이미 테이블이 있어도 덮어쓴다.


Insert Overwrite — 데이터만 교체

INSERT OVERWRITE orders
SELECT * FROM orders_new
  CREATE OR REPLACE INSERT OVERWRITE
스키마 변경 가능 (테이블 재생성) 불가 (스키마 유지)
Time Travel 이전 버전 사라짐 이전 버전 유지
용도 구조까지 바꿀 때 데이터만 교체할 때

INSERT OVERWRITE는 스키마를 유지하면서 데이터만 갈아끼우기 때문에 Time Travel로 이전 데이터 복구가 가능하다.


한 줄 정리

OPTIMIZE           → 작은 파일을 128MB로 합치기
ZORDER             → 자주 쓰는 컬럼 기준 정렬 (전체 재정렬)
Liquid Clustering  → ZORDER 개선판, 새 파일만 점진적 처리
VACUUM             → 7일 이상 된 파일 정리 (Time Travel 범위 축소)
COPY INTO          → 중복 없이 파일 적재 (멱등성)
CTAS               → 쿼리 결과로 테이블 생성
Insert Overwrite   → 데이터만 교체, 스키마 유지, Time Travel 가능

✓ Day 1: Spark 기초
✓ Day 2: Delta Lake
✓ Day 3: Auto Loader
✓ Day 4: Structured Streaming
✓ Day 5: Delta Live Tables
✓ Day 6: Workflows
✓ Day 7: Architecture + Notebooks + Git Folders
✓ Day 8: DataFrameReader API + Views + JOIN + 집계 + Window Functions
✓ Day 9: Spark UDF + Higher Order Functions
✓ Day 10: Delta Lake 심화 (OPTIMIZE, ZORDER, Liquid Clustering, VACUUM, COPY INTO)