IT/Spark

Spark - RDD vs Dataframes vs Datasets

물통꿀꿀이 2020. 2. 15. 23:31

RDD와 Dataframes, Datasets를 비교하는 글이 있어서 보려고 한다.

중간중간 의역 및 생략이 있을 수 있다. 때문에 보다 자세한 글은 아래 원문을 참조

https://databricks.com/blog/2016/07/14/a-tale-of-three-apache-spark-apis-rdds-dataframes-and-datasets.html


우리는 언제, 왜 RDD, Dataframes, Datasets를 사용해야 할까? 

Resilient Distributed Dataset (RDD)

RDD는 Spark 등장 이래로 주로 사용된 API 이다. Spark Core에서는 RDD는 변경할 수 없는(Immutable) 데이터의 집합으로 클러스터 내의 여러 노드에 분산되어 있다.

(Transformation, Action과 같은 low-level API를 지원한다.)


그럼 언제 RDD를 사용해야 할까? 일반적으로 사용되는 경우를 살펴보자.

- low-level API인 Transformation, Action을 사용할 때

- 데이터가 미디어와 같이 비구조화 형태로 되어 있을 때

- 데이터를 함수형 프로그래밍으로 조작하고 싶을 때

- 데이터를 처리할 때, 칼럼 형식과 같은 스키마를 굳이 따지고 싶지 않을 때

- 최적화를 굳이 신경쓰지 않을 때


그럼 RDD는 Spark 2.0에서는 어떻게 되었을까? deprecated 되었을까?

이후에도 알아 보겠지만 Dataframe, Dataset 와 함께 존재한다. (해당 타입이 RDD의 상위 개념에 속하기 때문)


Dataframes

RDD와 같이 Dataframe도 변경 할 수 없는 데이터 집합이다. 다만, 데이터가 RDB의 관계형 테이블처럼 칼럼이 존재한다. 따라서 대용량 데이터를 좀 더 쉽게 처리 할 수 있다.

또한 구조화 되어 있기 때문에 여러 데이터 엔지니어들이 쉽게 Spark에 접근 할 수 있다. (RDB와 같은 형태를 많은 사람들에게 익숙하기 때문에)

그러나 Spark 2.0에서 Dataframe API는 Datasets API와 통합되었다.



Datasets

Spark 2.0이 대두되면서, Dataset은 2가지 특징(strongly-typed API, uptyped API)을 가지게 되었다. 개념적으로 Dataframe은 제네릭(generic) 객체인 Dataset[Row]의 집합이며 Alias이다. (DataFrame = Dataset[Row])

Dataset API의 장점에 대해 알아보자.

Spark 2.0 이후로 Dataframe과 Dataset이 통합되면서 여러 가지 장점을 갖는다.


1. Static-typing & runtime type-safety

예를 들어 Spark SQL을 사용하면 실행 할 때까지 문법 에러를 알 수 없다. 반면에 Dataframe과 Dataset은 컴파일 시점에 에러를 잡을 수 있다. (물론 실행 할 때까지 존재하지도 않는 칼럼은 찾을 수 없다.) 또한 Dataset API는 람다 함수 및 JVM 타입 객체로 표현되기 때문에, 컴파일 시점에 타입을 검사할 수 있다. 



2. High-level abstraction and custom view into structured and semi-structured data

예를 들어 JSON으로 표현된 거대한 IoT 디바이스 데이터가 있다고 가정해보자. JSON은 반구조화 형태이지만 Dataset[DeviceIoTData]와 같은 strongly typed의 집합으로 구성된다. 

{
"device_id": 198164, "device_name": "sensor-pad-198164owomcJZ",
"ip": "80.55.20.25", "cca2": "PL", "cca3": "POL",
"cn": "Poland", "latitude": 53.080000, "longitude": 18.620000,
"scale": "Celsius", "temp": 21, "humidity": 65,
"battery_level": 8, "c02_level": 1408, "lcd": "red", "timestamp": 1458081226051
}
case class DeviceIoTData (battery_level: Long, c02_level: Long, cca2: String, cca3: String, cn: String, 
device_id: Long, device_name: String, humidity: Long, ip: String, latitude: Double, lcd: String,
longitude: Double, scale:String, temp: Long, timestamp: Long)
// read the json file and create the dataset from the 
// case class DeviceIoTData
// ds is now a collection of JVM Scala objects DeviceIoTData
val ds = spark.read.json(“/databricks-public-datasets/data/iot/iot_devices.json”).as[DeviceIoTData]

위의 코드를 보면,

1) JSON 데이터

2) 추출하기 위한 클래스

3) JSON 데이터를 읽어서 클래스 형태로 구성

이 중, 3)에서 데이터를 Dataset으로 구성하면서 타입을 DevcieIoTData 으로 명시한다. 


대부분의 사람들은 구조화된 데이터를 처리하는데 익숙하다. 이렇듯 타입이 명시된 데이터 집합인 Dataset으로 컴파일 시점에 데이터 뷰를 볼 수 있다. 게다가 Dataset[T] 형태는High-level 메소드로 쉽게 작업 할 수 있다.



3. Ease-of-use of APIs with structure

구조적 형태는 Spark에서 데이터를 다루는데 한계가 있을 수 도 있다. 그러나 Dataset은 쉽게 이해 할 수 있고, 데이터를 다양하게 표현 할 수 있다.

예시로 agg, select, sum, avg, map, filter, groupby를 사용하여 데이터를 다루는 것은 RDD의 각 row 필드를 사용하는 것보다 쉽다. 

// Use filter(), map(), groupBy() country, and compute avg() 
// for temperatures and humidity. This operation results in
// another immutable Dataset. The query is simpler to read,
// and expressive

val dsAvgTmp = ds.filter(d => {d.temp > 25}).map(d => (d.temp, d.humidity, d.cca3)).groupBy($"_3").avg()

//display the resulting dataset
display(dsAvgTmp)


4. Performance & Optimization

Dataframe와 Dataset은 Spark SQL 엔진 위에 탑재되어 있다. (Spark Stack 참조)

즉, 최적화된 논리적 및 물리적 쿼리 계획을 생성 할 수 있는 Catalyst를 사용 할 수 있다. 그러므로 R, Java, Scala, Python과 같은 언어도 같은 장점을 취할 수 있다.


다음으로 컴파일러가 데이터 타입 JVM 객체를 알고 있으므로, Encoders를 사용하여 명시화된 JVM 객체를 Tungsten 내부 메모리에 매핑한다. 때문에 효율적으로 JVM 객체를 직별화/반직렬화 시킬 수 있고 바이크도 또한 생성 할 수 있다.


그렇다면 언제 Dataframe, Dataset를 사용해야 할까?

- 도메인 API, 추상화 등등이 필요할 때

- filters, maps, aggergagion, 반구조화 데이터에서 람다 함수 등등이 필요할 때

- Catalyst 최적화 및 Tungsten 코드를 사용하고 싶을 때

- API를 단순화하여 사용하고 싶을때

- R, Python 사용자


(추가로 Dataframe, Dataset에서 RDD로 간단히 변환이 가능하다.)


Bringing It All Together

요약하자면 RDD, Dataframe 및 Dataset의 선택은 명확하다. (RDD는 저수준 기능 및 제어, Dataframe과 Dataset는 고수준 및 도메인 작접 그리고 최적화)