LLM WikiAccess-protected knowledge portal

WIKI

Apache Parquet ALP 인코딩: 부동소수점 컬럼을 ZSTD 수준으로 압축하면서 압축 해제를 100배 빠르게 만드는 방법

요약 Parquet 파일에 저장되는 FLOAT · DOUBLE 컬럼은 오랫동안 압축에 취약한 영역이었다. 카디널리티가 낮으면 RLE DICTIONARY가 작동하지만, 센서 값·지표·가격 같은 컬럼은 값 자체가 너무 다양해 딕셔너리가 거의 효과를 내지 못한다. 남은 선택지는 PLAIN 비압축 이나 ZSTD 같은 범용 바이트 압축인데, ZSTD는 CPU를 많이 쓴다. 2024년 SIGMOD에서 CWI의 Azim Afroozeh와

경로human/study/content/database-frontier/94-apache-parquet-alp-encoding-adaptive-lossless-floating-point.md
카테고리Study
태그#adaptive #encoding #floating #lossless #mysql #point #study

요약

Parquet 파일에 저장되는 FLOAT·DOUBLE 컬럼은 오랫동안 압축에 취약한 영역이었다. 카디널리티가 낮으면 RLE_DICTIONARY가 작동하지만, 센서 값·지표·가격 같은 컬럼은 값 자체가 너무 다양해 딕셔너리가 거의 효과를 내지 못한다. 남은 선택지는 PLAIN(비압축)이나 ZSTD 같은 범용 바이트 압축인데, ZSTD는 CPU를 많이 쓴다.

2024년 SIGMOD에서 CWI의 Azim Afroozeh와 Peter Boncz가 발표한 ALP(Adaptive Lossless floating-Point Compression)는 이 문제를 다른 방향으로 접근한다. 부동소수점 수의 10진수 구조를 이용해 "의사소수점(PseudoDecimal)" 경로와 "프런트비트 벡터화" 경로 중 하나를 값 집합에 맞게 자동 선택해, ZSTD와 유사한 압축률을 내면서 압축 해제 속도는 1~2자릿수 더 빠른 수준을 달성한다.

2026년 7월 29일, ALP 인코딩이 parquet-format 스펙에 공식 병합됐다. 인코딩 식별자 값은 10(ADAPTIVE_LOSSLESS_FLOATING_POINT)이다.


배경: Parquet 부동소수점 압축의 공백

기존 Parquet 인코딩의 한계

Parquet는 컬럼 유형에 따라 여러 인코딩을 제공한다. 정수형은 DELTA_BINARY_PACKED, 문자열은 RLE_DICTIONARY가 보통 효과적이다. 그러나 부동소수점 컬럼은 선택지가 빈약했다.

인코딩특성부동소수점 효과
PLAIN비압축 원본 저장없음
RLE_DICTIONARY값 사전 공유카디널리티 낮을 때만 효과적
BYTE_STREAM_SPLIT바이트 레인 분리압축률 낮음, 범용 압축기 보조 목적
DELTA_BINARY_PACKED정수 델타부동소수점 적용 불가

실제로 시계열 측정값, 금융 지표, 센서 데이터 같은 컬럼은 값마다 다르면서 IEEE 754 표현 패턴을 공유한다. 사람이 읽는 소수 표현(12.34, 0.0057, 99.9)이 내부적으로는 지수·가수·부호 비트로 분산되어 있어, 바이트 단위 범용 압축이 잘 작동하지 않는다.

ALP의 출발점: 부동소수점 수의 숨은 구조

10진수로 표현 가능한 부동소수점 수(f = i × 10^-d, 여기서 id는 정수)는 변환하면 작은 정수 배열이 된다. 이 정수는 DELTA_BINARY_PACKED으로 효율적으로 압축할 수 있다.

1.23  →  i=123, d=2
45.0  →  i=4500, d=2
0.007 →  i=7, d=3

모든 부동소수점 수가 이 구조를 갖지는 않는다. ALP는 이를 인정하고 두 가지 경로로 처리한다.


ALP 알고리즘: 두 가지 경로

FLOAT / DOUBLE 컬럼 벡터 단위(기본 1,024개) 처리 경로 선택기 (벡터마다 독립 결정) 10진수 구조 있음 경로 A PseudoDecimal (ALP-Decimals) 인코딩 방식 f = i × 10⁻ᵈ 변환 정수 i → 비트팩 예외값만 별도 저장 SIMD 친화적 비정형 부동소수점 경로 B Front-bit Vectorized (ALP-RD) 인코딩 방식 앞부분 비트(지수+부호) 델타 인코딩 뒷부분(가수) 비트팩 사전 없이 압축 Parquet 데이터 페이지 (ALP 헤더 7바이트 + 비트팩 데이터)
ALP 두 경로 알고리즘 흐름

경로 A: PseudoDecimal (ALP-Decimals)

센서 값, 환율, 측정 지표처럼 10진수로 표현 가능한 부동소수점 수에 사용된다.

  1. 지수 추출: 벡터 내 값들에서 최적 지수 d를 하나 선택한다.
  2. 정수 변환: 각 값 fi = round(f × 10^d) 로 변환한다.
  3. 비트팩: 변환된 정수 배열을 DELTA 인코딩 + 비트팩으로 압축한다.
  4. 예외 처리: 정수로 변환되지 않는 값(정밀도 손실 발생 가능성 있는 값)은 예외 목록에 원본 비트 그대로 기록한다.

전체 과정이 SIMD(AVX-512 등) 명령어로 벡터화된다.

경로 B: Front-bit Vectorized (ALP-RD)

과학적 계산 결과, 무작위 시뮬레이션 값처럼 10진수 구조가 없는 부동소수점 수에 사용된다.

  1. 비트 분리: IEEE 754 비트 표현을 앞부분(지수+부호)과 뒷부분(가수 하위 비트)으로 나눈다.
  2. 앞부분 압축: 지수 비트는 벡터 내에서 공통 패턴을 공유하는 경우가 많아 델타 인코딩으로 줄인다.
  3. 뒷부분 비트팩: 가수 하위 비트를 폭(width)을 측정해 최소 비트로 팩한다.

Parquet 포맷 통합 (2026년 7월 29일)

스펙 변경 내용

2026년 7월 29일 parquet-format 레포지터리에 ALP 인코딩이 공식 병합됐다. 핵심 변경 사항은 다음과 같다.

항목
인코딩 식별자10 (ADAPTIVE_LOSSLESS_FLOATING_POINT)
적용 가능 타입FLOAT (FLOAT32), DOUBLE (FLOAT64)
페이지 헤더 추가 오버헤드7바이트
기본 벡터 크기1,024개 값
최소·최대 벡터 크기8 ~ 32,768개

ALP 페이지 헤더 구조

각 데이터 페이지 앞에 7바이트 ALP 헤더가 붙는다.

[1바이트] 경로 플래그 (0 = PseudoDecimal, 1 = Front-bit)
[1바이트] 지수(exponent) 값 d (PseudoDecimal 경로에서만 의미 있음)
[2바이트] 예외 개수 (exception count)
[2바이트] 예외 비트 폭 (exception bit width)
[1바이트] 비트팩 폭 (bitpack width)

경로는 벡터 단위로 독립 선택된다. 같은 컬럼 내에서도 페이지마다 경로가 달라질 수 있다.


압축률과 속도 비교

압축률: ZSTD와 유사, PLAIN보다 크게 우수

아래 수치는 SIGMOD 2024 논문 기준이며, 데이터셋에 따라 달라질 수 있다.

인코딩압축률압축 해제 속도특이사항
PLAIN1.0× (기준)매우 빠름압축 없음
BYTE_STREAM_SPLIT + ZSTD2.5~4×느림CPU 부담 큼
ALP (PseudoDecimal)2~6×매우 빠름SIMD 벡터화
ALP (Front-bit)1.5~3×빠름비정형 값 처리
Gorilla (시계열 전용)2~5×빠름시계열에만 최적

ALP가 ZSTD와 비슷한 압축률을 내면서도 압축 해제 속도가 1~2자릿수(10~100배) 빠른 이유는, ZSTD가 바이트 수준의 엔트로피 코딩(Huffman, ANS)을 쓰는 반면 ALP는 SIMD 정수 연산만으로 처리하기 때문이다.

어떤 컬럼에 효과적인가

효과 큼 (경로 A)
• 센서·IoT 측정값
• 금융 가격·환율
• 의료 수치 데이터
• 로그 지표(latency ms)
효과 있음 (경로 B)
• 머신러닝 가중치
• 물리 시뮬레이션
• GPS 좌표 (정밀 소수)
• 집계 통계 중간값
효과 제한적
• NaN / Inf 비율 높음
• 랜덤 해시 기반 값
• 균등 분포 실수
• 이미 ZSTD 압축됨
ALP 효과 예상 컬럼 유형

운영 시사점

언제 ALP를 켜야 하는가

ALP는 모든 FLOAT/DOUBLE 컬럼에 자동으로 최적인 것은 아니다. 스펙에 추가됐다는 것은 라이브러리가 지원을 시작한다는 의미이지, 기본값이 바뀐다는 뜻이 아니다.

켜면 좋은 경우:

주의가 필요한 경우:

라이브러리 지원 현황 (2026년 8월 기준)

라이브러리상태
DuckDB쓰기·읽기 지원
parquet-cpp (Arrow)구현 진행 중
parquet-go논의 중
Spark parquet 모듈지원 계획 미정
pandas (PyArrow 백엔드)Arrow 지원 후 연동 예정

스펙 병합이 먼저이고, 각 라이브러리의 실제 구현은 별도 일정을 따른다. 새 인코딩을 쓰려면 쓰기 라이브러리가 지원해야 하고, 읽기 라이브러리도 인코딩 식별자 10을 인식해야 한다.

도입 체크리스트


요점 정리


References