Running Cost-Efficient Export Workloads at Uber

Author: Pankaj Mohapatra, Arun Mahadeva Iyer, Balajee Nagasubramaniam (Uber) | Source: uber.com/blog | Published: 2026


한 줄 요약

DSAR 같은 export 워크로드가 작은 결과셋을 위해 전체 히스토리를 반복 스캔해 오래된 데이터를 계속 hot하게 유지하고 auto-class tiering을 무력화하는데, Hudi column stats + 술어 컬럼 정렬이 broad scan을 narrow file selection으로 바꾼다.

핵심 주장/내용

  • Export workload의 특징: 컴플라이언스·프라이버시·운영 export 흐름에서 흔하고 결과셋은 작지만 검색 공간이 데이터 전체 히스토리에 걸친다. 날짜로 파티션된 대형 트랜잭션·팩트 테이블에 point query나 좁은 술어 쿼리를 발행하고, 반복적으로(주 여러 번) 실행되며, 같은 쿼리 패턴을 매번 다른 파라미터로 반복하고, 타겟 레코드가 전체 데이터셋의 작은 일부인데도 선택성에도 불구하고 full-table scan을 수행한다
    • 구체 예가 DSAR(Data Subject Access Request) — 개인이 조직이 보유한 자기 개인 데이터에 접근할 것을 요구하는 법적 요청
  • GCS auto-class tiering을 깨뜨리는 방식: GCS는 관측된 접근 패턴에 따라 객체를 스토리지 클래스 사이로 자동 이동시켜 원칙적으로는 차가운 데이터가 시간이 지나며 싼 티어로 간다. 그러나 이 메커니즘이 모든 파일을 반복적으로 건드리는 워크로드에 의해 무력화된다. 파일 메타데이터나 footer를 반복 스캔하는 것만으로도 객체를 hot하게 유지해 저비용 클래스로의 전환을 막는다
    • 전형적 접근 패턴 기반의 바람직한 분포는 약 60% Standard, 15% Nearline, 10% Coldline, 15% Archive인데, 모든 파일에 대한 반복 read가 차가운 데이터를 hot하게 유지하면 100%가 Standard에 머물고 가장 비싼 스토리지 비용을 낸다
    • 분석 워크로드는 더 많은 데이터를 처리하지만 최근 파티션에 대해서라 오래된 데이터가 차가워지게 둔다. Export는 정반대 — 작은 타겟 집합을 위해 히스토리 전체를 반복 검색한다. 이 “건초더미에서 바늘 찾기”가 반복되고 건초더미가 테이블 전체이면 데이터를 hot하게 유지하고 auto-class 전환을 막고 스토리지·검색 비용을 올린다
    • 결과셋 크기만으로 짐작하는 것보다 훨씬 큰 스토리지 접근 footprint. 반복 실행이 스토리지 비용, 검색 비용, objects.get·objects.list 같은 메타데이터 무거운 Class B 연산을 올리고, 그러지 않으면 차갑게 남았을 파일에 반복 스캔을 강제해 쿼리 성능도 떨어뜨린다. 대규모 데이터셋에서는 상당한 리소스 오버헤드와 peak bandwidth 한도 초과 위험도
  • secondary index가 도움이 안 되는 이유: Hudi Secondary Index는 non-primary-key 컬럼 술어를 가속해 엔진이 스캔 전에 파일을 프루닝하게 설계되었다. 하지만 핵심 질문은 인덱스가 파일을 프루닝할 수 있느냐가 아니라 추가 메타데이터·운영 비용을 정당화할 만큼 충분히 프루닝하느냐였다. 대상 테이블에서 같은 subject의 레코드가 대부분의 파일에 흩어져 있어서, secondary index가 후보 row를 찾는 데 도움이 되어도 여전히 큰 파일 집합으로 매핑될 수 있고 엔진은 여전히 높은 파일 스캔·메타데이터 비용을 낸다
  • 작동하는 것 — 두 아이디어의 결합:
    • Hudi column stats — Hudi는 메타데이터 테이블에 추적 컬럼의 min·max·null count·total count 같은 컬럼 레벨 통계를 유지한다. 이 메타데이터가 기저 Parquet 파일과 별도로 저장되므로 엔진이 파일을 직접 읽지 않고 무관한 파일을 프루닝할 수 있다
      • Parquet도 유용한 컬럼 통계를 저장하지만 그것은 파일 footer에 산다. footer에 의존하는 것은 여전히 데이터 파일을 건드리므로 충분하지 않고, 그 반복 read가 파일을 hot하게 유지해 auto-class가 더 차갑고 싼 티어로 옮기는 것을 막는다
      • Hudi는 파일 프루닝 메타데이터를 테이블 레벨에서 유지해 이 footer read 문제를 해결한다. 통계를 발견하려고 많은 파일을 여는 대신 엔진이 Hudi 메타데이터 테이블을 질의해 스캔 시작 전에 어느 파일이 관련 있는지 판단한다
    • 테이블 정렬 — export 쿼리는 보통 rider ID, driver ID, courier ID 같은 subject 식별자로 구동된다. subject의 레코드가 많은 파일에 흩어져 있으면 column stats조차 엔진이 테이블 상당 부분을 검사하게 남겨둘 수 있다. 술어 컬럼으로 정렬하면 유사한 키가 함께 클러스터되고 파일 레벨 min/max 범위가 조여져 프루닝이 더 선택적이 된다
    • column stats가 프루닝 메커니즘을 제공하고 정렬이 그 효과를 개선한다. 함께 넓은 파일 스캔을 좁은 파일 선택으로 바꾼다
  • 왜 정렬 + secondary index가 아닌가: 정렬이 프루닝을 훨씬 효과적으로 만들고, 이 지점에서 Hudi column stats가 이미 secondary index보다 작은 메타데이터 footprint로 효과적 파일 프루닝을 제공한다. column stats는 주로 파일 수와 추적 컬럼 수에 따라 스케일하지만 secondary index는 인덱싱된 값에 대한 lookup 매핑을 유지해야 한다
    • 트레이드오프가 명확하다: 테이블이 정렬되어 있지 않으면 secondary index가 스캔 비용을 유의미하게 바꿀 만큼 파일을 프루닝하지 못하고, 테이블이 정렬되어 있으면 Hudi column stats가 더 단순하고 스토리지 효율적인 해법이다

주요 수치 / 사실

  • 벤치마크: 실제 테이블 파티션을 술어 컬럼(user ID)으로 정렬하고 술어 100·200·500·1,000·5,000개에 대해 타겟 row가 흩어진 Parquet 파일 수를 비교 → 정렬된 파티션에서 타겟 파일 비율이 극적으로 감소
  • 정렬 후 효율 이득: 디스크 사용량 24.8% 감소와 함께 파일 프루닝(스캔 중 아예 건드리지 않음), GCS egress 감소, 컴퓨트 감소를 low·mid·high 술어 값에 대해 측정
  • 테이블 정렬은 압축 효율도 개선해 스토리지를 최적화한다 — 동일한 값을 물리적으로 함께 클러스터링하면 총 데이터 footprint가 작아진다
  • 다른 산업의 같은 접근 패턴: 금융(규제·감사·분쟁 워크플로가 특정 계정·엔티티에 대한 다년 히스토리 요구), 헬스케어·생명과학(컴플라이언스 리뷰, 환자 이력 접근, 감사), 이커머스·리테일(사기 조사, 고객 지원, 주문 이력 export), 애드테크·측정(attribution·개인화·컴플라이언스를 위한 타임라인 재구성), 보안·identity(조사, 접근 리뷰 — 특정 사용자·principal의 전체 로그인·활동 이력)
  • 다음 단계: 클라이언트마다 다른 술어 컬럼을 쓰는 데이터셋에서는 단일 컬럼 정렬이 균일한 이득을 주지 못하므로, 컬럼 수가 늘어날 때 표준 사전식 정렬의 한계를 극복하기 위해 Z-order space-filling curve 탐색. 그리고 이런 needle-in-a-haystack 접근 패턴을 자동 탐지하는 프레임워크 — 인덱싱·정렬 비용을 잠재 쿼리 절감과 저울질해 ROI가 정당화될 때만 레이아웃 최적화 파이프라인을 트리거
  • 교훈: 접근 패턴이 스토리지 비용을 좌우한다 — 좁고 히스토리를 관통하는 조회는 전형적 분석 쿼리와 매우 다르게 행동하고 순진한 테이블 레이아웃이 불균형한 스토리지·egress 비용을 만든다 / 파일 레이아웃이 tiering만큼 중요하다 — auto-class는 파일이 차가워질 만큼 오래 건드려지지 않을 때만 절감을 준다 / 메타데이터 기반 프루닝이 결정적 — Parquet footer에 의존하는 것은 footer read가 여전히 파일을 건드리므로 tiering에 역행한다 / 일회성 재작성이 장기 절감을 열 수 있다 / 최고의 결과는 end-to-end 설계에서 나온다 — 스토리지 레이아웃·메타데이터·쿼리 실행·오케스트레이션이 모두 함께 작동해야 하고, 아니면 비용이 한 레이어에서 다른 레이어로 옮겨질 뿐이다

관련 위키


Source: 원문 보기