반응형

아파치 아이스버그란?

아이스버그는 대용량 분석 데이터셋을 위한 오픈 테이블 포맷입니다. 기존 하이브 테이블이나 파케이 파일의 한계를 극복하기 위해 넷플릭스에서 개발했고, 현재는 아파치 재단의 탑레벨 프로젝트입니다.

 

기존 방식의 문제점:

  • 스키마 변경 시 전체 테이블 재생성 필요
  • 동시 쓰기 작업 시 데이터 일관성 문제
  • 파티션 정보를 수동으로 관리해야 함
  • 작은 파일들이 많이 생성되어 성능 저하

핵심 아키텍처

메타데이터 계층구조:

테이블 메타데이터
├── 스냅샷 (Snapshot) - 특정 시점의 테이블 상태
├── 매니페스트 리스트 (Manifest List) - 매니페스트 파일들의 목록
├── 매니페스트 파일 (Manifest) - 데이터 파일들의 메타데이터
└── 데이터 파일 (Data Files) - 실제 파케이/ORC 파일들

이 계층구조 덕분에 메타데이터만 업데이트하여 빠른 작업이 가능합니다.

ACID 트랜잭션과 동시성 제어

Atomicity (원자성): 모든 변경사항이 하나의 스냅샷으로 커밋되거나 전체가 롤백됩니다.

Consistency (일관성): 스키마 검증과 제약조건 확인을 통해 데이터 일관성을 보장합니다.

Isolation (격리성): 스냅샷 격리를 통해 동시 읽기/쓰기 작업이 서로 간섭하지 않습니다. 각 트랜잭션은 시작 시점의 스냅샷을 기준으로 작업합니다.

Durability (지속성): 커밋된 변경사항은 영구적으로 저장됩니다.

 

동시성 제어 메커니즘:

sql
-- 두 개의 동시 INSERT 작업이 가능
Session A: INSERT INTO table VALUES (1, 'data1')
Session B: INSERT INTO table VALUES (2, 'data2')
-- 둘 다 성공적으로 커밋됨

타임 트래블 쿼리

과거 특정 시점의 데이터를 조회할 수 있는 기능입니다.

sql
-- 특정 스냅샷 ID로 조회
SELECT * FROM table VERSION AS OF 1234567890

-- 특정 시간으로 조회  
SELECT * FROM table TIMESTAMP AS OF '2024-01-01 10:00:00'

-- 특정 시간 이전 데이터 조회
SELECT * FROM table FOR SYSTEM_TIME AS OF '2024-01-01'

 

활용 사례:

  • 데이터 감사 및 규정 준수
  • A/B 테스트 결과 비교
  • 데이터 변경사항 추적
  • 실수로 삭제된 데이터 복구

스키마 진화 (Schema Evolution)

기존 데이터에 영향을 주지 않고 스키마를 변경할 수 있습니다.

 

지원되는 변경사항:

sql
-- 컬럼 추가 (기존 데이터는 NULL 또는 기본값)
ALTER TABLE users ADD COLUMN email STRING

-- 컬럼 이름 변경 (기존 쿼리도 계속 작동)
ALTER TABLE users RENAME COLUMN name TO full_name

-- 컬럼 타입 변경 (안전한 변경만 허용)
ALTER TABLE users ALTER COLUMN age TYPE BIGINT

-- 컬럼 삭제 (실제로는 숨김 처리)
ALTER TABLE users DROP COLUMN temp_column

 

스키마 호환성:

  • 이전 버전 쿼리가 계속 작동
  • 새로운 컬럼은 기본값으로 채워짐
  • 타입 변경은 안전한 경우만 허용 (INT → BIGINT는 OK, BIGINT → INT는 불가)

파티셔닝과 히든 파티셔닝

기존 하이브 방식의 문제:

sql
-- 하이브: 파티션 컬럼을 명시적으로 지정해야 함
INSERT INTO hive_table PARTITION(year=2024, month=01) 
SELECT col1, col2 FROM source WHERE date_col >= '2024-01-01'

 

아이스버그의 히든 파티셔닝:

sql
-- 파티션 생성
CREATE TABLE iceberg_table (
  id BIGINT,
  name STRING,
  created_at TIMESTAMP
) PARTITIONED BY (days(created_at))

-- 삽입 시 파티션 자동 결정
INSERT INTO iceberg_table 
SELECT id, name, created_at FROM source

 

파티션 진화:

sql
-- 기존: 일별 파티션
ALTER TABLE table SET PARTITION SPEC (days(created_at))

-- 변경: 월별 파티션 (기존 데이터는 그대로 유지)
ALTER TABLE table SET PARTITION SPEC (months(created_at))

성능 최적화 기능

컴팩션 (Compaction): 작은 파일들을 큰 파일로 병합하여 쿼리 성능을 향상시킵니다.

sql
-- 수동 컴팩션
CALL system.rewrite_data_files('db.table')

-- 자동 컴팩션 설정
ALTER TABLE table SET TBLPROPERTIES (
  'write.target-file-size-bytes'='134217728'  -- 128MB
)

 

Z-Ordering: 관련된 데이터를 물리적으로 가까이 배치하여 스캔 성능을 개선합니다.

sql
CALL system.rewrite_data_files(
  table => 'db.table',
  strategy => 'sort',
  sort_order => 'customer_id, order_date'
)

 

블룸 필터:

sql
ALTER TABLE table SET TBLPROPERTIES (
  'write.bloom-filter.enabled'='true',
  'write.bloom-filter.columns'='customer_id'
)

다른 솔루션과의 비교

기능 Iceberg Delta Lake Hudi
 ACID 트랜잭션
타임 트래블
스키마 진화
엔진 지원 Spark, Flink, Trino 등 주로 Spark 주로 Spark
히든 파티셔닝
파티션 진화

실제 사용 사례

1. CDC 파이프라인:

sql
-- 변경사항을 실시간으로 반영
MERGE INTO target_table t
USING cdc_stream s ON t.id = s.id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *

 

2. 데이터 웨어하우스 현대화: 기존 하이브 테이블을 아이스버그로 마이그레이션하여 성능과 관리성 향상

 

3. 스트리밍 데이터 처리:

java
// Flink로 실시간 데이터를 아이스버그 테이블에 저장
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.addSource(kafkaSource)
   .addSink(IcebergSink.forRowData(table)
                      .tableLoader(tableLoader)
                      .build());

 

4. 데이터 품질 관리:

sql
-- 데이터 변경 이력 추적
SELECT * FROM table.history

-- 스냅샷 정보 조회
SELECT * FROM table.snapshots

이러한 기능들 덕분에 아이스버그는 현대적인 데이터 레이크하우스 아키텍처의 핵심 구성요소로 자리잡고 있습니다. 특히 데이터의 신뢰성과 일관성이 중요한 엔터프라이즈 환경에서 매우 유용합니다.

 

반응형

+ Recent posts