LLM WikiAccess-protected knowledge portal
← 스터디 홈
147편 · 약 13분

Apache DataFusion 55: Sort Pushdown·TopK 동적 임계값·MERGE INTO로 Rust 쿼리 엔진이 넓어진 방법

요약

Apache DataFusion 55.0.0이 2026년 7~8월에 출시됐다. Delta Lake(delta-rs), LanceDB, Ballista, InfluxDB IOx, GlareDB 등 수십 개 시스템의 쿼리 실행 백엔드를 담당하는 DataFusion은 이번 릴리스에서 쿼리 계획 단계부터 IO를 건너뛰는 구조적 최적화를 완성했다.

세 가지 핵심 변화:

  1. Sort Pushdown: ORDER BY … LIMIT k 쿼리에서 Parquet 행 그룹 수준의 IO를 생략한다.
  2. TopK 동적 임계값: 처리 중 임계값을 지속 갱신하고, 더 이상 기여할 수 없는 행 그룹을 바운더리마다 잘라낸다.
  3. MERGE INTO: SQL 표준 MERGE INTO 구문을 지원해 Iceberg·Delta Lake의 upsert 워크플로를 DataFusion 엔진에서 직접 처리한다.

topk_tpch 벤치마크 11개 쿼리 가운데 5개가 3~4× 빨라졌고, 전체 벤치마크 런타임이 44% 감소했다.

  • 릴리스 이슈: github.com/apache/datafusion/issues/22393
  • 기반 기술: Apache Arrow 파일 형식, Parquet 통계(min/max), Rust async I/O

DataFusion이란 무엇인가

DataFusion은 Apache Arrow 프로젝트 하위의 Rust 기반 인메모리 쿼리 엔진이다. SQL과 DataFrame API를 제공하며, 실행 계획(logical plan → physical plan)을 Arrow RecordBatch 스트림 위에서 병렬로 수행한다.

단독 DB가 아니라 빌딩 블록으로 설계됐다:

  • delta-rs: Delta Lake 쓰기·읽기 엔진
  • LanceDB: 벡터 DB 분석 쿼리
  • InfluxDB IOx: 시계열 쿼리 실행
  • Ballista: 분산 DataFusion 클러스터
  • Comet: Spark 물리 계획 인터셉터 (DataFusion이 JVM 대신 실행)

DataFusion이 빨라지면 이 생태계 전체가 혜택을 받는다.


Sort Pushdown와 TopK 최적화

문제: ORDER BY … LIMIT k의 비용

SELECT user_id, event_time, amount
FROM transactions
ORDER BY amount DESC
LIMIT 100;

위 쿼리는 amount 내림차순 상위 100개를 반환한다. 나이브하게 실행하면:

  1. 모든 Parquet 파일에서 모든 행 읽기
  2. 전체를 메모리에서 정렬
  3. 상위 100개 반환

파일이 수십 GB라면 IO와 정렬 모두 낭비다.

Parquet 통계 기반 프루닝

Parquet은 행 그룹(기본 128MB)마다 각 컬럼의 min, max, null_count를 푸터에 저장한다. DataFusion은 이미 WHERE amount > 1000 같은 필터를 통계로 프루닝했다. Sort Pushdown은 TopK 쿼리에서 동적으로 이 통계를 활용한다.

행 그룹 1
amount min=500
amount max=9200
처리 후 임계값
heap의 100번째 = 7800
↓ 다음 그룹 체크
행 그룹 2
amount min=100
amount max=6500
max(6500) < 임계값(7800)
→ IO 완전 생략
↓ 건너뜀
행 그룹 3
amount min=3000
amount max=12000
max(12000) ≥ 임계값
→ IO 수행 후 처리
임계값 → 9100으로 상승
↓ 임계값 갱신
이후 행 그룹들도
임계값과 비교
점점 더 많이 건너뜀
Sort Pushdown + TopK 동적 임계값 동작 방식

동적 임계값의 핵심

기존 TopK 구현은 임계값을 쿼리 종료 시에만 알았다. DataFusion 55는 다음을 구현했다:

  • TopKExec이 최소 힙(min-heap)을 유지: 현재까지 본 상위 k개의 최솟값이 임계값
  • 매 행 그룹 경계마다 파일 통계와 임계값 비교
  • 행_그룹.max < 임계값이면 해당 행 그룹의 Parquet 파일을 열지 않음

처리가 진행될수록 힙의 임계값은 높아지고, 생략 가능한 행 그룹이 늘어난다. 이 효과는 데이터가 ORDER BY 컬럼과 어느 정도 상관된 순서로 저장될 때 극대화된다.

다중 컬럼 사전 순 통계 재정렬

ORDER BY dept ASC, salary DESC, hire_date ASC LIMIT 50

복합 정렬 키에서 통계 비교는 (dept_min, dept_max) → (salary_min, salary_max) 순서로 이루어진다. DataFusion 55는 여러 컬럼의 통계를 사전 순(lexicographic)으로 조합해 복합 정렬 쿼리에서도 행 그룹을 정확하게 프루닝한다.


MERGE INTO 지원

MERGE INTO target t
USING source s ON t.id = s.id
WHEN MATCHED AND s.deleted = true THEN DELETE
WHEN MATCHED THEN UPDATE SET amount = s.amount
WHEN NOT MATCHED THEN INSERT (id, amount) VALUES (s.id, s.amount);

DataFusion 55 이전에는 MERGE를 외부 레이어(Delta Lake, Iceberg 커넥터)에서 직접 구현해야 했다. 55부터는:

  • SQL 플래너가 MERGE INTO를 논리 계획으로 변환
  • 물리 계획 레벨에서 Match/NoMatch 분기 실행
  • TableProvider 훅을 통해 스토리지 레이어가 실제 변경을 처리

이로써 delta-rs, Iceberg 커넥터가 DataFusion의 표준 MERGE 경로를 재사용할 수 있게 됐다.


Parquet 가상 컬럼: row_number

DataFusion 55는 Parquet 파일 수준의 물리 행 번호를 row_number라는 가상 컬럼으로 노출한다.

SELECT file_path, row_number, user_id
FROM read_parquet('data/*.parquet', hive_partition=true);

활용 사례:

  • 중복 제거: 같은 row_number 기준으로 소스 파일과 대상 파일 조인
  • 디버깅: 특정 행 그룹의 특정 행을 역추적
  • Parquet 파일 조인: 두 파일에서 같은 물리 행 번호를 가진 행을 빠르게 결합

file_row_index UDF도 추가됐다:

SELECT file_row_index(scan_id) as row_idx, * FROM my_table;

GroupValuesColumn 타입 지원 확장

DataFusion의 GroupValuesColumn은 GROUP BY 집계에서 그룹 키를 추적하는 내부 구조다. 55 이전에는 기본 타입(Int, Float, Utf8 등)만 지원했다. 55부터:

  • List, LargeList: 배열 컬럼으로 GROUP BY 가능
  • Struct: 중첩 구조체 컬럼으로 GROUP BY 가능
  • Map: 키-값 구조로 GROUP BY 가능

이로써 JSON 컬럼이나 반정형 데이터를 포함한 쿼리에서 그룹 집계가 가능해진다.


스칼라 UDF null 전파 메타데이터

55부터 UDF 정의에 null 전파 엄격성을 명시할 수 있다:

ScalarUDF::new(
    "my_func",
    ...,
    volatility: Volatility::Immutable,
    null_propagation: NullPropagation::Strict,  // 인수가 null이면 반드시 null 반환
)

Strict로 설정하면 옵티마이저가 null 입력에 대해 함수 호출을 생략하고 바로 null을 반환한다. 대규모 테이블에서 null 비율이 높을 때 실질적인 성능 개선이 된다.


성능 벤치마크

topk_tpch 벤치마크(TPC-H 기반 상위 K 쿼리 11개) 결과:

쿼리 유형개선 전개선 후배율
단일 컬럼 ORDER BY LIMIT (정렬 상관도 높음)기준3~4× 빠름3~4×
복합 컬럼 ORDER BY LIMIT기준1.5~2× 빠름1.5~2×
기타 쿼리 (Sort Pushdown 미해당)기준동일
전체 벤치마크기준44% 감소1.8×

성능 향상이 큰 쿼리는 데이터가 ORDER BY 컬럼과 어느 정도 정렬되어 있고, Parquet 행 그룹의 min/max 선택도가 높은 경우다.


DataFusion 55 핵심 변화 구조도 SQL 쿼리 ORDER BY … LIMIT / MERGE INTO 논리 계획 (Logical Plan) Sort + Limit 노드 / Merge 노드 물리 계획 (Physical Plan) TopKExec + ParquetScan / MergeExec TopKExec + Sort Pushdown • min-heap 유지 (현재 임계값) • 행 그룹 경계마다 min/max 비교 • max < 임계값 → IO 완전 생략 MergeExec (MERGE INTO) • MATCHED / NOT MATCHED 분기 • TableProvider 훅으로 스토리지 위임 • Delta Lake / Iceberg 커넥터 재사용
DataFusion 55 주요 기능 구조도

DataFusion을 사용하는 팀의 운영 관점

Sort Pushdown 효과 극대화

  • Parquet 파일을 ORDER BY 컬럼 기준으로 정렬해 저장: 행 그룹 min/max의 선택도가 높아진다. Z-order(Hilbert curve) 정렬도 단일 컬럼에서는 효과적이다.
  • 행 그룹 크기 조정: 크기가 작으면 임계값 갱신이 더 자주 일어나 프루닝 세분성이 올라가지만, 푸터 메타데이터 오버헤드가 증가한다. 64~256MB 범위에서 실측하는 것을 권장한다.
  • Parquet Column Index 활성화: 행 그룹 내 페이지 수준 통계도 포함하면 더 정밀한 프루닝이 가능하다 (DataFusion은 Column Index를 지원한다).

MERGE INTO 주의사항

  • TableProvider::merge() 훅이 없는 스토리지 레이어는 MERGE INTO를 소프트웨어 레벨에서 처리해야 한다 (DELETE + INSERT). 스토리지별 훅 구현 여부를 확인해야 한다.
  • Iceberg의 위치 삭제(positional delete)나 Delta Lake의 삭제 벡터(deletion vector)를 활용하면 MERGE 성능이 크게 달라진다.

GroupValuesColumn 중첩 타입 활용

Parquet으로 저장된 반정형 로그(Struct 컬럼)에 GROUP BY를 적용할 때, DataFusion 55 이전에는 UDF 우회나 Flatten이 필요했다. 55부터는 직접 사용 가능하다:

SELECT metadata['source'] AS src, COUNT(*)
FROM events
GROUP BY metadata['source'];

업그레이드 시 주의

  • GroupValuesColumn 내부 구조 변경으로 집계 결과의 반환 순서가 달라질 수 있다 (ORDER BY 없이 GROUP BY 사용 시).
  • NullPropagation::Strict 설정 UDF가 null 입력에서 다른 동작을 기대했다면 재검토 필요.

Open questions

  • Sort Pushdown 효과는 데이터 정렬도(sortedness)에 크게 의존한다. 임의 순서 데이터에서 성능 회귀 없음이 확인됐는지는 추가 실측이 필요하다.
  • MERGE INTO의 Iceberg V3 삭제 벡터 통합이 완료됐는지 미확인.
  • DataFusion 56 릴리스 일정과 포함 기능 미정.

References

  • https://github.com/apache/datafusion/issues/22393 — Release DataFusion 55.0.0 (Jul/Aug 2026) issue tracker
  • https://datafusion.apache.org/blog/output/2026/06/12/datafusion-54.0.0/ — DataFusion 54.0.0 블로그 (이전 릴리스, 맥락용)
  • https://www.mail-archive.com/[email protected]/msg138056.html — Sort Pushdown EPIC 이슈 토론
  • https://docs.rs/crate/datafusion/latest — DataFusion 최신 API 문서
  • https://github.com/apache/datafusion — Apache DataFusion GitHub 저장소
  • https://arrow.apache.org/docs/format/Columnar.html — Apache Arrow 컬럼 형식 (Parquet 통계 맥락)