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에 결과를 돌려준다.
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 엔진에는 구조적 제약이 있다:
- 직렬화 경계: Spark의 내부 행 형식(UnsafeRow)과 Arrow/Parquet 컬럼 형식 사이의 변환 비용
- GC 오버헤드: JVM 힙에서 중간 데이터를 관리하면서 발생하는 GC 압력
- SIMD 활용 한계: Rust나 C++처럼 CPU 벡터 명령어를 세밀하게 제어하기 어려움
- Parquet 읽기 비용: Java Parquet 리더는 최신 Parquet 스펙의 페이지 인덱스·딕셔너리 최적화를 완전히 활용하지 못하는 경우가 있음
DataFusion Comet는 이 실행 레이어를 Rust + Arrow로 교체한다.
Comet의 아키텍처
핵심 설계 원칙: 엔드투엔드 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 Join | ✅ | 1.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가 특히 유용한 경우:
- 정규식(regex): Spark의 정규식 처리는 Java
java.util.regex에 의존하며 Rust의regex크레이트와 에지 케이스에서 동작이 다를 수 있다. Dispatch를 통해 Spark와 정확히 동일한 동작을 보장한다. - 커스텀 UDF가 포함된 서브트리: UDF는 JVM에서 실행되어야 하지만, 주변 필터·집계는 네이티브 그대로 유지된다.
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% 절감 |
단, 모든 쿼리가 같은 수준으로 가속되지는 않는다.
가속 효과가 큰 경우:
- 대규모 조인 + 집계 (Hash Join, Sort Merge Join이 Spark 실행 시간의 대부분인 경우)
- Parquet 스캔이 병목인 경우 (페이지 인덱스·딕셔너리 프루닝 효과)
- 셔플 데이터 규모가 큰 경우 (Arrow IPC 직렬화 비용 < Java 직렬화 비용)
가속 효과가 제한적인 경우:
- 복잡한 JVM UDF가 실행의 대부분인 경우 (UDF는 Comet이 가속하지 않음)
- Spark에서 Comet 지원 범위 밖의 연산자가 많은 계획
도입 방법
의존성 추가
<!-- 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.0Spark 설정
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 | ✅ |
운영 체크리스트
- [ ] Spark 버전이 3.4+인지 확인했는가 (3.3 이하는 미지원)
- [ ] JNI 라이브러리가 대상 OS/아키텍처(x86_64 Linux, Apple Silicon)에서 빌드됐는지 확인했는가
- [ ]
spark.comet.exec.shuffle.enabled=true설정 시 셔플 파티션 크기와 메모리 설정이 충분한지 검토했는가 - [ ]
spark.comet.explain.verbose=true로 폴백 발생 비율을 측정하고 핵심 쿼리에서 폴백이 최소화됐는지 확인했는가 - [ ] JVM UDF를 많이 사용하는 워크로드라면 UDF를 Arrow UDF나 Pandas UDF로 전환 가능한지 검토했는가
- [ ] GC 로그와 JNI 메모리 사용량을 모니터링 대시보드에 포함했는가 (Comet은 JVM 힙 외부 메모리를 사용)
- [ ] Iceberg 테이블을 사용한다면 Iceberg 1.11과 Comet 1.0.0의 조합이 검증됐는지 확인했는가
References
- Apache DataFusion Comet 1.0.0 Release (공식 블로그, 2026-08-07): https://datafusion.apache.org/blog/output/2026/08/07/datafusion-comet-1.0.0/
- Apache DataFusion Comet 프로젝트 GitHub: https://github.com/apache/datafusion-comet
- Apache DataFusion Comet 문서: https://datafusion.apache.org/comet/
- Apache DataFusion Comet — Comet Accelerator Overview: https://datafusion.apache.org/comet/overview.html
- Apache Data Lakehouse Weekly Aug 5-12 (DataFusion Comet 1.0.0 언급): https://dev.to/alexmercedcoder/apache-data-lakehouse-weekly-august-5-august-12-2026-2j40
- Apache DataFusion Comet 0.17.0 Release (직전 릴리스, 2026-06-20): https://datafusion.apache.org/blog/output/2026/06/20/datafusion-comet-0.17.0/
- Accelerating Iceberg Rust Development with DataFusion Comet: https://iceberg.apache.org/blog/accelerating-iceberg-rust-development-with-datafusion-comet/