주요 컨텐츠로 이동

세 가지 Apache Spark API 이야기: RDD 대 DataFrame 및 Dataset

언제, 왜 사용해야 할까요?

A Tale of Three Apache Spark APIs: RDDs vs DataFrames and Datasets

발행일: 2016년 7월 14일

오픈 소스2 min read

작성자: Jules Damji

개발자들에게 가장 매력적인 것은 생산성을 높여주고, 사용하기 쉬우며, 직관적이고 표현력이 풍부한 API 세트입니다. Apache Spark가 개발자들에게 어필하는 점 중 하나는 대규모 데이터셋을 Scala, Java, Python, R 등 다양한 언어로 쉽게 조작할 수 있는 API입니다.

이 블로그에서는 Apache Spark 2.2 이상 버전에서 사용할 수 있는 세 가지 API 세트인 RDD, DataFrame, Dataset을 살펴보고, 각 세트를 언제 사용해야 하는지, 성능 및 최적화 이점은 무엇인지, 그리고 RDD 대신 DataFrame과 Dataset을 사용해야 하는 시나리오는 무엇인지 설명합니다. 주로 DataFrame과 Dataset에 초점을 맞출 것인데, 이는 Apache Spark 2.0에서 이 두 API가 통합되었기 때문입니다.

이 통합의 주요 동기는 학습해야 할 개념의 수를 줄이고 구조화된 데이터를 처리할 수 있는 방법을 제공하여 Spark를 단순화하려는 노력입니다. 구조를 통해 Spark는 도메인별 언어 구문과 같은 더 높은 수준의 추상화 및 API를 제공할 수 있습니다.

Resilient Distributed Dataset (RDD)

RDD는 Spark 출시 초기부터 사용자의 기본 API였습니다. 핵심적으로 RDD는 데이터의 요소들로 이루어진 불변의 분산 컬렉션으로, 클러스터의 노드에 분산되어 저수준 API를 통해 변환(transformations)작업(actions)을 병렬로 수행할 수 있습니다.

RDD는 언제 사용해야 할까요?

다음과 같은 시나리오 또는 일반적인 사용 사례를 고려할 때 RDD를 사용합니다.

  • 데이터셋에 대한 저수준 변환 및 작업 제어가 필요할 때
  • 데이터가 텍스트 스트림 또는 미디어 스트림과 같이 구조화되지 않은 경우
  • 도메인별 표현식보다 함수형 프로그래밍 구문을 사용하여 데이터를 조작하고 싶을 때
  • 데이터를 처리하거나 이름 또는 열로 데이터 속성에 액세스할 때 열 형식과 같은 스키마를 적용하는 것에 신경 쓰지 않을 때
  • 구조화되거나 반구조화된 데이터에 대해 DataFrame 및 Dataset에서 제공하는 일부 최적화 및 성능 이점을 포기할 수 있을 때

Apache Spark 2.0에서 RDD는 어떻게 되나요?

궁금하실 수 있습니다. RDD가 2등 시민이 되나요? 지원이 중단되나요?

답변은 단호하게 아니요!입니다.

더 나아가, 아래에서 볼 수 있듯이 간단한 API 메서드 호출을 통해 DataFrame 또는 Dataset과 RDD 간에 자유롭게 전환할 수 있으며, DataFrame과 Dataset은 RDD를 기반으로 구축됩니다.

DataFrames

RDD와 마찬가지로 DataFrame은 불변의 분산 데이터 컬렉션입니다. RDD와 달리 데이터는 관계형 데이터베이스의 테이블처럼 명명된 열로 구성됩니다. 대규모 데이터셋 처리를 더욱 쉽게 만들기 위해 설계된 DataFrame은 개발자가 분산 데이터 컬렉션에 구조를 적용할 수 있도록 하여 더 높은 수준의 추상화를 제공합니다. 분산 데이터를 조작하기 위한 도메인별 언어 API를 제공하며, 전문 데이터 엔지니어 외에도 더 넓은 사용자층에게 Spark를 접근 가능하게 합니다.

Apache Spark 2.0 웹 세미나 미리 보기 및 이후 블로그에서 Spark 2.0에서 DataFrame API가 Dataset API와 병합되어 라이브러리 전반의 데이터 처리 기능을 통합할 것이라고 언급했습니다. 이 통합 덕분에 개발자는 이제 학습하거나 기억해야 할 개념이 줄어들고 Dataset이라는 단일의 고수준의 타입 안전 API를 사용할 수 있습니다.

Datasets

Spark 2.0부터 Dataset은 아래 표와 같이 강타입 API와 비타입 API의 두 가지 뚜렷한 특성을 가집니다. 개념적으로 DataFrame은 일반 객체 컬렉션인 Dataset[Row]별칭으로 생각할 수 있으며, 여기서 Row는 일반적인 비타입 JVM 객체입니다. 반면에 Dataset은 Scala의 case 클래스 또는 Java의 클래스로 정의된 타입에 따라 결정되는 강타입 JVM 객체 컬렉션입니다.

타입 및 비타입 API

언어 주요 추상화
Scala Dataset[T] & DataFrame (Dataset[Row]의 별칭)
Java Dataset[T]
Python* DataFrame
R* DataFrame

참고: Python과 R은 컴파일 타임 타입 안전성이 없으므로, 비타입 API인 DataFrame만 사용합니다.

Dataset API의 이점

Spark 개발자는 Spark 2.0의 DataFrame 및 Dataset 통합 API를 통해 여러 가지 이점을 얻을 수 있습니다.

1. 정적 타이핑 및 런타임 타입 안전성

정적 타이핑 및 런타임 안전성을 스펙트럼으로 간주할 때, SQL이 가장 덜 제한적이고 Dataset이 가장 제한적입니다. 예를 들어, Spark SQL 문자열 쿼리에서는 런타임에 구문 오류를 알게 되지만 (런타임에서 발생할 수 있으며 비용이 많이 들 수 있음), DataFrame과 Dataset에서는 컴파일 타임에 오류를 잡을 수 있어 개발 시간과 비용을 절약할 수 있습니다. 즉, DataFrame에서 API에 포함되지 않은 함수를 호출하면 컴파일러가 이를 감지합니다. 그러나 런타임까지 존재하지 않는 열 이름을 감지하지는 못합니다.

스펙트럼의 가장 끝에는 가장 제한적인 Dataset이 있습니다. Dataset API는 모두 람다 함수와 JVM 타입 객체로 표현되므로, 타입 매개변수의 불일치는 컴파일 타임에 감지됩니다. 또한, Dataset을 사용할 때 분석 오류도 컴파일 타임에 감지할 수 있어 개발 시간과 비용을 절약할 수 있습니다.

이 모든 것은 Spark 코드의 구문 및 분석 오류에 따른 타입 안전성 스펙트럼으로 해석될 수 있으며, Dataset은 가장 제한적이지만 개발자에게 가장 생산적입니다.

2. 구조화 및 반구조화 데이터에 대한 고수준 추상화 및 사용자 정의 뷰

Dataset[Row] 컬렉션으로서의 DataFrame은 반구조화된 데이터에 대한 구조화된 사용자 정의 뷰를 제공합니다. 예를 들어, JSON으로 표현된 방대한 IoT 장치 이벤트 데이터셋이 있다고 가정해 보겠습니다. JSON은 반구조화된 형식이기 때문에, 강력한 타입의 특정 Dataset[DeviceIoTData] 컬렉션으로 Dataset을 사용하는 것이 적합합니다.

Scala case 클래스를 사용하여 각 JSON 항목을 DeviceIoTData라는 사용자 정의 객체로 표현할 수 있습니다.

다음으로 JSON 파일에서 데이터를 읽을 수 있습니다.

위 코드에서 내부적으로 세 가지 일이 발생합니다.

  1. Spark는 JSON을 읽고 스키마를 추론하여 DataFrame 컬렉션을 생성합니다.
  2. 이 시점에서 Spark는 정확한 타입을 알지 못하므로 데이터를 DataFrame = Dataset[Row], 즉 일반 Row 객체 컬렉션으로 변환합니다.
  3. 이제 Spark는 Dataset[Row] -> Dataset[DeviceIoTData], 즉 클래스 DeviceIoTData에 의해 결정되는 타입별 Scala JVM 객체로 변환합니다.

구조화된 데이터를 다루는 대부분의 사람들은 데이터를 열 형식으로 보거나 객체 내의 특정 속성에 액세스하는 데 익숙합니다. Dataset[ElementType] 타입 객체의 컬렉션인 Dataset을 사용하면 컴파일 타임 안전성과 강타입 JVM 객체에 대한 사용자 정의 뷰를 모두 원활하게 얻을 수 있습니다. 또한 위 코드에서 생성된 강타입 Dataset[T]는 고수준 메서드를 사용하여 쉽게 표시하거나 처리할 수 있습니다.

3. 구조화된 API의 사용 편의성

구조화는 Spark 프로그램이 데이터를 다룰 수 있는 제어 기능을 제한할 수 있지만, 풍부한 의미론과 고수준 구성으로 표현할 수 있는 쉬운 도메인별 연산을 제공합니다. 하지만 대부분의 계산은 Dataset의 고수준 API로 수행할 수 있습니다. 예를 들어, RDD 행의 데이터 필드를 사용하는 것보다 Typed 객체인 DeviceIoTData의 Dataset에 접근하여 agg, select, sum, avg, map, filter 또는 groupBy 연산을 수행하는 것이 훨씬 간단합니다.

도메인별 API로 계산을 표현하는 것이 RDD의 관계 대수식보다 훨씬 간단하고 쉽습니다. 예를 들어, 아래 코드는 불변 Dataset을 생성하기 위해 filter()map()을 사용합니다.

4. 성능 및 최적화

위의 모든 이점과 더불어, 두 가지 이유로 DataFrame 및 Dataset API를 사용할 때의 공간 효율성과 성능 향상을 간과할 수 없습니다.

첫째, DataFrame 및 Dataset API는 Spark SQL 엔진 위에 구축되었기 때문에 Catalyst를 사용하여 최적화된 논리적 및 물리적 쿼리 계획을 생성합니다. R, Java, Scala 또는 Python DataFrame/Dataset API 전반에 걸쳐 모든 관계형 쿼리는 동일한 코드 최적화 프로그램을 거쳐 공간 및 속도 효율성을 제공합니다. 반면, Dataset[T] 타입 API는 데이터 엔지니어링 작업을 위해 최적화되었으며, 타입이 없는 Dataset[Row](DataFrame의 별칭)는 훨씬 더 빠르고 대화형 분석에 적합합니다.

둘째, Spark as a compiler는 Dataset 타입 JVM 객체를 이해하므로, Encoder를 사용하여 타입별 JVM 객체를 Tungsten의 내부 메모리 표현으로 매핑합니다. 결과적으로, Tungsten Encoder는 JVM 객체를 효율적으로 직렬화/역직렬화할 수 있으며, 뛰어난 속도로 실행될 수 있는 컴팩트한 바이트코드를 생성할 수 있습니다.

DataFrame 또는 Dataset은 언제 사용해야 할까요?

  • 풍부한 의미론, 고수준 추상화 및 도메인별 API를 원하면 DataFrame 또는 Dataset을 사용하세요.
  • 처리 과정에서 고수준 표현식, 필터, 맵, 집계, 평균, 합계, SQL 쿼리, 열 액세스 및 반정형 데이터에 대한 람다 함수 사용이 필요한 경우 DataFrame 또는 Dataset을 사용하세요.
  • 컴파일 타임에 더 높은 수준의 타입 안전성을 원하고, 타입이 지정된 JVM 객체를 사용하며, Catalyst 최적화를 활용하고, Tungsten의 효율적인 코드 생성의 이점을 누리고 싶다면 Dataset을 사용하세요.
  • Spark 라이브러리 전반에 걸쳐 API의 통합 및 단순화를 원하면 DataFrame 또는 Dataset을 사용하세요.
  • R 사용자인 경우 DataFrames를 사용하세요.
  • Python 사용자인 경우 DataFrames를 사용하고, 더 많은 제어가 필요한 경우 RDD로 돌아가세요.

.rdd 메서드 호출을 통해 DataFrame 및/또는 Dataset을 RDD로 원활하게 상호 운용하거나 변환할 수 있습니다. 예를 들어,

모두 종합하기

요약하자면, RDD 또는 DataFrame 및/또는 Dataset을 언제 사용해야 하는지에 대한 선택은 명확해 보입니다. 전자는 저수준 기능과 제어를 제공하는 반면, 후자는 사용자 정의 보기와 구조를 허용하고, 고수준 및 도메인별 연산을 제공하며, 공간을 절약하고, 뛰어난 속도로 실행됩니다.

Spark의 초기 릴리스에서 얻은 교훈, 즉 개발자를 위해 Spark를 단순화하는 방법과 성능을 최적화하는 방법을 살펴보면서, 저수준 RDD API를 DataFrame 및 Dataset과 같은 고수준 추상화로 승격시키고 Catalyst optimizer 및 Tungsten 위에 이 통합 데이터 추상화를 구축하기로 결정했습니다.

요구 사항과 사용 사례에 맞는 API(DataFrame 및/또는 Dataset 또는 RDD API)를 선택하세요. 하지만 구조화된 데이터와 반정형 데이터를 다루는 대부분의 개발자 그룹에 속하게 되더라도 놀라지 않을 것입니다.

다음 단계

Databricks에서 Apache Spark 2.2를 사용해 볼 수 있습니다.

세 가지 Apache Spark API의 이야기: RDD 대 DataFrame 및 Dataset에 대한 Spark Summit 발표를 시청할 수도 있습니다.

아직 가입하지 않았다면 지금 Databricks를 사용해 보세요.

다음 몇 주 동안 Structured Streaming에 대한 일련의 블로그를 게시할 예정입니다. 계속 지켜봐 주세요.

(이 글은 AI의 도움을 받아 번역되었습니다. 원문이 궁금하시다면 여기를 클릭해 주세요)

게시물을 놓치지 마세요

관심 있는 카테고리를 구독하고 최신 게시물을 받은편지함으로 받아보세요