LLM WikiAccess-protected knowledge portal

WIKI

Apache DataFusion Comet 1.0: Spark 쿼리를 Arrow 네이티브 Rust 엔진으로 가속하는 방법

요약 2026년 8월 7일, Apache DataFusion 프로젝트가 Comet 1.0.0 을 발표했다. 2년간의 인큐베이션을 마치고 도달한 첫 번째 안정 릴리스다. Comet은 Apache Spark의 쿼리 실행을 DataFusion의 Rust 네이티브 엔진으로 가속하는 플러그인이다. Spark JVM 코드를 바꾸지 않고 Spark 계획 plan 을 그대로 받아서 Arrow 컬럼 형식으로 처리한 뒤 Spark에 결과를 돌려

경로human/study/content/database-frontier/123-apache-datafusion-comet-1-0-spark-native-arrow-acceleration.md
카테고리Study
태그#acceleration #arrow #comet #mysql #native #spark #study

요약

2026년 8월 7일, Apache DataFusion 프로젝트가 Comet 1.0.0을 발표했다. 2년간의 인큐베이션을 마치고 도달한 첫 번째 안정 릴리스다. Comet은 Apache Spark의 쿼리 실행을 DataFusion의 Rust 네이티브 엔진으로 가속하는 플러그인이다. Spark JVM 코드를 바꾸지 않고 Spark 계획(plan)을 그대로 받아서 Arrow 컬럼 형식으로 처리한 뒤 Spark에 결과를 돌려준다.

1.0.0의 의미는 단순한 버전 번호가 아니다. 호환성 인터페이스가 안정화됐다는 신호다. Spark 운영팀이 프로덕션 도입을 검토할 수 있는 기준선이 만들어진 것이다.

TPC-DS SF 1000(1TB) 기준 평균 2배 속도 향상, 약 50% 비용 절감이 보고됐다.

이 글은 Comet의 아키텍처, 1.0.0에서 달라진 점, 그리고 Spark 운영 엔지니어가 도입을 판단할 때 살펴봐야 할 기준을 다룬다.


배경: Spark의 JVM 기반 실행 엔진의 한계

Apache Spark는 Tungsten 프로젝트(Spark 1.4, 2015)부터 코드젠(codegen)을 통해 JVM 오버헤드를 줄여왔다. Tungsten은 Spark 쿼리를 JVM 바이트코드로 컴파일해서 행(row) 반복 대신 일괄 처리한다.

그러나 JVM 엔진에는 구조적 제약이 있다:

  1. 직렬화 경계: Spark의 내부 행 형식(UnsafeRow)과 Arrow/Parquet 컬럼 형식 사이의 변환 비용
  2. GC 오버헤드: JVM 힙에서 중간 데이터를 관리하면서 발생하는 GC 압력
  3. SIMD 활용 한계: Rust나 C++처럼 CPU 벡터 명령어를 세밀하게 제어하기 어려움
  4. Parquet 읽기 비용: Java Parquet 리더는 최신 Parquet 스펙의 페이지 인덱스·딕셔너리 최적화를 완전히 활용하지 못하는 경우가 있음

DataFusion Comet는 이 실행 레이어를 Rust + Arrow로 교체한다.


Comet의 아키텍처

Apache DataFusion Comet 1.0 아키텍처 Spark 애플리케이션 (변경 없음) DataFrame / SQL API Catalyst 옵티마이저 Physical Plan 생성 Tungsten 코드젠 Physical Plan 가로채기 Comet JVM Layer (Spark Plugin API) CometSparkSessionExtension 등록 Comet Physical Rules → 계획 교체 JNI 브리지 JNI → Apache Arrow C Data Interface Comet Native Engine (Rust / DataFusion) 조인 연산자 Hash/Sort/Merge/ BroadcastHash Join 집계·윈도우 HashAggregate Window Function Parquet 읽기 CachedParquetFileReader 페이지 인덱스 캐시 셔플·익스체인지 Arrow 네이티브 셔플 외부 정렬 지원 Generator explode posexplode Codegen Dispatch (1.0.0 신기능) 미지원 표현식 감지 → 해당 표현식만 Spark JVM 코드젠 호출 (배치 전체를 JVM으로 보내지 않음) → 400+ Spark 표현식 지원 + Spark 시맨틱 정밀도 보장 (정규식 등 동작 일치) → Arrow 배치는 네이티브 파이프라인에 머뭄. 전체 폴백 없음. Arrow 컬럼 결과 반환 → JNI → Spark Parquet (Iceberg/Hive/HDFS/S3) 페이지 인덱스, 딕셔너리, 블룸 필터 셔플 스토리지 (로컬 디스크) Arrow IPC 형식으로 직렬화
Apache DataFusion Comet 아키텍처: Spark 계획 가로채기와 Arrow 네이티브 실행

핵심 설계 원칙: 엔드투엔드 Arrow 네이티브

Comet의 가장 중요한 설계 결정은 결과를 Arrow 배치로 교환한다는 것이다. Spark와 Comet 사이의 데이터 교환 경계에서 Arrow의 C Data Interface를 사용해 직렬화 없이 메모리 버퍼를 전달한다.

Parquet 읽기  → Arrow RecordBatch
연산자 처리   → Arrow RecordBatch
셔플(교환)    → Arrow IPC 직렬화 → 디스크 → Arrow IPC 역직렬화
Spark 반환   → C Data Interface → UnsafeRow 변환 (경계에서만)

이 설계 덕분에 중간 연산들 사이에서 Spark의 UnsafeRow 형식으로 변환하는 비용이 발생하지 않는다.


1.0.0의 주요 변경 사항

연산자 커버리지 확장

Comet 1.0.0은 Spark의 4가지 조인 연산자를 모두 가속한다:

조인 유형가속 여부비고
Hash Join브로드캐스트 포함
Sort Merge Join
Shuffle Hash Join
Broadcast Nested Loop Join1.0.0에서 추가

Generator 연산자 (explode, explode_outer, posexplode, posexplode_outer)도 지원된다. 배열 컬럼을 풀어내는 작업이 Arrow 네이티브로 처리된다.

Codegen Dispatch

Comet의 기존 한계는 지원하지 않는 Spark 표현식이 하나라도 계획 트리에 있으면 해당 연산자 서브트리 전체를 JVM으로 되돌려야 했다는 점이다.

1.0.0의 Codegen Dispatch는 이 문제를 근본적으로 해결한다.

기존 방식:
  미지원 표현식 발견 → 서브트리 전체를 Spark JVM 폴백 → Arrow 배치 변환 오버헤드

Codegen Dispatch:
  미지원 표현식 발견 → 해당 표현식 노드만 Spark JVM 코드젠 호출
  나머지 연산자·표현식은 계속 Arrow 네이티브 파이프라인 유지
  Arrow 배치 변환 없음. 코드젠 함수가 Arrow 버퍼를 직접 읽고 씀

Codegen Dispatch가 특히 유용한 경우:

Parquet 최적화

CachedParquetFileReaderFactory: Parquet 파일 메타데이터(페이지 인덱스 포함)를 세션 캐시에 저장한다. 같은 파일을 반복해서 읽는 쿼리에서 메타데이터 파싱 비용이 사라진다.

통계 기반 프루닝 개선: 스키마 어댑터에서 항등(identity) 캐스트를 제거해 Parquet 컬럼 통계에 기반한 파일·행 그룹 프루닝이 올바르게 동작하도록 수정됐다.

Iceberg 1.11 지원

Comet 1.0.0은 Apache Iceberg 1.11과 함께 동작하며, Iceberg 테이블 포맷 v3 기능 중 전체 테이블 암호화(full table encryption)를 처음으로 지원한다.


성능 특성

TPC-DS 결과

TPC-DS(Scale Factor 1000, 1TB) 기준 측정값(DataFusion Comet 블로그 기준):

지표개선
전체 쿼리 평균 속도~2× 향상
비용 효율~50% 절감

단, 모든 쿼리가 같은 수준으로 가속되지는 않는다.

가속 효과가 큰 경우:

가속 효과가 제한적인 경우:


도입 방법

의존성 추가

<!-- Maven, Scala 2.13 기준 -->
<dependency>
    <groupId>org.apache.datafusion</groupId>
    <artifactId>comet-spark-spark3_5_2-scala2.13</artifactId>
    <version>1.0.0</version>
</dependency>
# pip 패키지 (PySpark 환경)
pip install datafusion-comet==1.0.0

Spark 설정

spark = SparkSession.builder \
    .config("spark.plugins", "org.apache.comet.CometPlugin") \
    .config("spark.comet.enabled", "true") \
    .config("spark.comet.exec.enabled", "true") \
    .config("spark.comet.exec.shuffle.enabled", "true") \
    .config("spark.comet.exec.shuffle.mode", "auto") \
    .config("spark.comet.explain.verbose", "false") \  # 프로덕션 false
    .getOrCreate()

폴백 확인

Comet이 특정 연산자를 지원하지 못하면 해당 연산자를 Spark JVM으로 폴백한다. EXPLAIN EXTENDED로 계획을 확인하거나 Comet 로그에서 폴백 발생 위치를 추적할 수 있다.

# 어떤 연산자가 Comet 가속, 어떤 것이 폴백인지 확인
spark.conf.set("spark.comet.explain.verbose", "true")
df.explain()
# 출력에서 CometExec (가속) vs SparkExec (폴백) 구분

호환성 표

Spark 버전Comet 1.0.0 지원비고
Spark 3.4
Spark 3.5권장
Spark 4.0
Scala 2.12 / 2.13각각 별도 아티팩트
Java 11 / 17

운영 체크리스트


References