LLM WikiAccess-protected knowledge portal

WIKI

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

경로human/study/content/database-frontier/147-apache-datafusion-55-sort-pushdown-topk-merge-into.md
카테고리Study
태그#merge #mysql #pushdown #sort #study #topk

요약

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% 감소했다.


DataFusion이란 무엇인가

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

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

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는 다음을 구현했다:

처리가 진행될수록 힙의 임계값은 높아지고, 생략 가능한 행 그룹이 늘어난다. 이 효과는 데이터가 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부터는:

이로써 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);

활용 사례:

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부터:

이로써 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 효과 극대화

MERGE INTO 주의사항

GroupValuesColumn 중첩 타입 활용

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

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

업그레이드 시 주의


Open questions

References