728x90
cache()
test_df.cache()
# test_df를 캐싱
test_df.storageLevel
# org.apache.spark.storage.StorageLevel = StorageLevel(disk, memory, deserialized, 1 replicas)
persist()
import org.apache.spark.storage.StorageLevel # storage 명시를 위한 library import
test2_df.persist(StorageLevel.MEMORY_AND_DISK) # test2_df에 persist를 하면서 storage lvl을 명시
test2_df.storageLevel
# org.apache.spark.storage.StorageLevel = StorageLevel(disk, memory, deserialized, 1 replicas)
storage level
~Ser 은 원본이 아닌 Serealize 된 형태로 저장한다는 것, 저장용량에서의 이점은 있지만, 저장할 때와 읽을 때 SER, deSER로 인한 CPU사용량 증가가 있음
Level |
Space Used |
CPU Time |
In memory |
On disk |
Nodes with data |
MEMORY_ONLY |
High |
Low |
Y |
N |
1 |
MEMORY_ONLY_2 |
High |
Low |
Y |
N |
2 |
MEMORY_ONLY_SER |
Low |
High |
Y |
N |
1 |
MEMORY_ONLY_SER_2 |
Low |
High |
Y |
N |
2 |
MEMORY_AND_DISK |
High |
Medium |
Some |
Some |
1 |
MEMORY_AND_DISK_2 |
High |
Medium |
Some |
Some |
2 |
MEMORY_AND_DISK_SER |
Low |
High |
Some |
Some |
1 |
MEMORY_AND_DISK_SER_2 |
Low |
High |
Some |
Some |
2 |
DISK_ONLY |
Low |
High |
N |
Y |
1 |
DISK_ONLY_2 |
Low |
High |
N |
Y |
2 |
* MEMORY_AND_DISK: 메모리 공간에 더이상 저장할 수 없는 경우 디스크에 저장
위 표의 Storage Level은 아래 다섯가지의 속성의 조합으로 만들어졌다: userDisk, useMemory, useOffHeap, deserialized, replication
- userDisk : 메모리에 들어가지 않는 파티션은 디스크에 기록된다. 디스크 IO 비용도 크므로 이 옵션을 사용하는 경우는 재연산 비용이 큰 경우가 될 것이다. (재연산의 비용이 크지 않은 경우 일부 파티션을 재연산하는 것이 더 빠를 수도 있다.)
- useMemory : 메모리에 저장되거나 직접 디스크에 기록된다.
- useOffHeap : Tachyon과 같은 executor 밖의 외부 시스템에 저장. 메모리이슈가 심각하거나 클러스터가 혼잡한 편이고 파티션이 자꾸 메모리에서 제거된다면 고려해볼만 하다.
- deserialized : 직렬화되지 않은 Java 객체로 저장된다. MEMORY_ONLY_SER 처럼 suffix로 _SER이 붙는 옵션들은 직렬화를 사용한다.
(RDD가 메모리에 들어가기 너무 크다면 우선 MEMORY_ONLY_SER 옵션으로 직렬화를 시도해본다. RDD에 빨리 접근하도록 유지하면서도 저장에 필요한 메모리는 줄어든다.) - replication : 영속화 데이터의 복사본 개수를 정수로 지정. default = 1.
cache() | persist() | |
공통점 | Spark로 데이터를 다룰 때 action 수행 시점마다 로드되지 않고, 한번 로드한 데이터를 메모리상에 상주 시키는 메서드 |
|
차이점 | RDD와 DF인지에 따라 default storage level이 달라짐 ● RDD.cache() 의 default storage level = StorageLevel.MEMORY_ONLY ● DF.cache() default storage level = StorageLevel.MEMORY_AND_DISK |
RDD, DF의 storage level을 명시해서 사용해야 함 |
사용하는 경우
- 반복적인 연산
동일한 데이터세트에 대해 반복적으로 연산을 수행한다면 이 데이터세트를 영속화해두는 것이 좋음. 매번 연산할 때마다 데이터세트가 메모리 내에 존재하고 있는 것이 보장되므로 성능 향상을 기대할 수 있음 - 동일 RDD에 대해 여러 번의 액션 호출
- 각 파티션의 연산 비용이 너무 큰 경우
여러번 사용하지 않더라도, 중간 결과를 저장하여 실패 시의 비용을 줄일 수 있음. 일반적으로 좁은 트랜스포메이션은 넓은 트랜스포메이션보다는 빠르지만, 파티션별 모델 훈련이나 매우 컬럼이 많은 행으로 작업하는 등 일부 좁은 트랜스포메이션이 클러스터의 executor의 처리량보다 더 큰 GC 오버헤드나 메모리 부담을 만들어낸다면 체크포인팅이나 off_heap 영속화가 빛을 발할 수 있음
참조:
https://nabillera.tistory.com/entry/Spark-%EA%B3%B5%EB%B6%80-%EA%B5%AC%EC%A1%B0-RDD-Storage-Level
728x90
댓글