← 학습 카테고리

Learn

Spark

38개 모듈 · 현재 34번째

Spark 모듈 34/38 spark-learn-34

AQE를 껐을 때와 켰을 때 — small files problem을 숫자로 확인하기

PySpark Tutorial: Build a Real Pipeline and Read the Spark UI — Darshil Parmar PySpark Tutorial: Build a Real Pipeline and Read the Spark UI — "The cost of losing that safety net shows up on disk" 구간 (22~24페이지)

이 모듈을 다 읽으면

  • 동일한 257행 데이터를 AQE 끄고/켜고 각각 저장했을 때 파일 개수와 용량이 왜 그렇게 크게 차이 나는지 설명할 수 있다
  • small files problem이 로컬 실습에서는 드러나지 않고 운영 환경(예: 시간마다 S3에 적재)에서 왜 문제가 되는지 설명할 수 있다
  • AQE를 켠 채로 두고 shuffle.partitions를 손으로 튜닝하는 것을 최후 수단으로 남겨야 하는 이유를 설명할 수 있다

동일한 257행짜리 daily DataFrame을 AQE를 끈 상태와 켠 상태로 각각 Parquet에 저장하면, AQE를 끈 쪽은 151개 파일에 187.6KB, AQE를 켠 쪽은 1개 파일에 3.4KB가 나온다. 데이터는 완전히 동일한데 저장 용량이 55배 차이 나는 이유는 Parquet 파일 하나하나가 몇 행을 담고 있든 스키마와 푸터를 반드시 포함하기 때문이다. 노트북 환경에서는 이 차이가 흥미로운 정도지만, 시간마다 S3에 적재되는 운영 테이블에서는 이것이 바로 small files problem이 되어, 이후 쿼리가 실제 데이터를 읽는 시간보다 파일을 여는 데 더 많은 시간을 쓰게 만든다. 그래서 AQE는 켠 채로 두고 출력 파일 개수를 관찰하는 편이 낫고, shuffle.partitions를 잡마다 손으로 낮추던 옛 조언은 AQE가 없던 시절의 것이다. 그럼에도 데이터 분포를 Spark보다 더 잘 아는 경우이거나 파일 레이아웃이 여전히 원하는 대로 나오지 않을 때는 repartition이나 coalesce를 쓰기 직전 단계에 배치하는 것이 정답이다.

동일한 257행, 151개 파일과 1개 파일

daily.write.mode("overwrite").parquet(...)를 AQE를 끈 상태와 켠 상태로 각각 실행하면, AQE off는 151개 파일에 총 187.6KB, AQE on은 단 1개 파일에 3.4KB가 만들어진다. 담긴 데이터는 완전히 동일한 257행인데도 저장 용량이 55배 차이 나는 이유는, Parquet 파일 하나하나가 몇 행을 담든 상관없이 자체 스키마와 푸터(footer)를 반드시 포함하기 때문이다. AQE가 셔플 파티션을 200개에서 1개로 병합해 준 덕분에 쓰기 단계의 출력 파일 수도 같이 줄어든 것이다.

핵심 포인트

  • 동일한 257행을 저장했는데 AQE off는 151개 파일(187.6KB), AQE on은 1개 파일(3.4KB)이 나왔다
  • 차이의 원인은 Parquet 파일마다 행 수와 무관하게 스키마·푸터 오버헤드가 붙기 때문이다

small files problem이 로컬에서는 안 보이고 운영에서 드러나는 이유

노트북에서 187.6KB짜리 151개 파일은 그저 흥미로운 숫자에 불과하지만, 같은 파이프라인이 시간마다 S3 같은 객체 스토리지에 적재되는 운영 테이블이라면 이야기가 달라진다. 파일 하나를 여는 데도 스토리지 메타데이터 조회, 스키마 파싱 같은 고정 비용이 들기 때문에, 파일 개수가 누적되면 이후 쿼리가 실제 데이터를 읽는 시간보다 파일을 여는 데 더 많은 시간을 쓰게 된다. 이것이 실무에서 흔히 말하는 small files problem이며, 이 실습은 그 문제가 왜 생기는지를 로컬 환경에서도 재현 가능한 숫자로 보여준다.

핵심 포인트

  • 파일 하나를 여는 데는 행 수와 무관한 고정 비용(메타데이터 조회, 스키마 파싱)이 든다
  • 적재 주기가 잦은 운영 테이블일수록 작은 파일이 누적되어 쿼리가 파일을 여는 데 더 많은 시간을 쓰게 된다

언제 shuffle.partitions를 손으로 만져야 하는가

AQE를 켠 채로 두고 출력 파일 개수를 관찰하는 것이, 잡마다 spark.sql.shuffle.partitions를 손으로 낮게 설정하는 것보다 나은 기본 전략이다. shuffle.partitions를 낮게 설정하라는 예전 조언은 AQE가 존재하지 않던 시절에 나온 것이기 때문이다. 다만 데이터 분포를 Spark의 런타임 추정보다 더 잘 아는 경우이거나, AQE를 켜도 여전히 파일 레이아웃이 원하는 대로 나오지 않는 경우에는 shuffle.partitions를 직접 조정하거나, 쓰기 직전 단계에 repartition() 또는 coalesce()를 추가하는 것이 적절한 대응이다.

핵심 포인트

  • AQE를 켠 채로 출력 파일 개수를 관찰하는 것이 기본 전략이고, shuffle.partitions 수동 하향 조정은 AQE 이전 시대의 조언이다
  • 데이터 분포를 더 잘 알거나 파일 레이아웃이 여전히 문제라면 repartition/coalesce를 쓰기 직전에 추가하는 것이 적절한 대응이다