Data가 메모리 용량보다 클 때?

in-memory는 거짓말이었다..?! Spark가 어떻게 동작할까.

애초에 메모리에 모든 데이터가 안들어간다는 것이었다면?

partition 단위로 일을 처리하는 것인데, 메모리 용량이 적어서 operator가 작동 안하면..? 여기서 말하는 메모리 용량은 executior 메모리이다. 평소에 storage 메모리는 안쓰는데, executor 메모리가 가득 차면 eviction이 일어나서 storage 메모리로 밀려나서 저장하게 된다.

스파크는 stage마다 계산을 통째로 하는데, 스테이지마다 처리한 파티션을 전부 저장하지 않고, 최종 계산 성공한 RDD의 파티션들만 저장한다. 그리고 Cache는 Storage memory에, checkpoint는 디스크에 파티션을 저장한다. 이 캐시는 LRU 캐시니까 가장 나중에 사용되었던 캐시를 제거하고 저장시킨다!

그리고 off-heap: executor 밖에 있는, 힙 메모리 밖에 있는 것을 쓴다.

더 작고 많은 파티션이 있다면: 병렬처리를 더 많이 하고, 필요한 태스크당 메모리가 작아진다.

LRU는 cache나 persist할 때만 적용된다. MEMORY_ONLY: storage 캐시 용량 부족하면 그냥 날려버린다. operator가 자주 spill한다면, 그리고 계산량이 작은 태스크가 많다면 쓰는게 낫다. MEMORY_AND_DISK: 부족하면 디스크에 적는다. → 디스크에서 가져오는게 다시 계산하는 것보다 빠를 때. 태스크 끝나고 저장하는 양이 많을 때 쓴다.

Unpersist는 메모리의 캐시를 전부 날려버리니까 속도가 빨라진다. 앞으로 안 쓸 데이터들은 날려버리자.

블록이 캐시되기 위해서는 storage 메모리 안에 들어가야 한다. 블록이 너무 크면 repartitioning을 하자.

Spark는 기본적으로 파티션을 코어 개수에 맞춰서 하는데, 그래도 블록이 크면 강제로 repartition 해야함

Operator의 메모리가 부족할 때

sort, agg, join, shuffle을 할 때 메모리 부족하면 spill → repartition으로 사이즈 줄이고 개수 늘리자.

메모리의 사이즈를 조정하는 방법도 있고, 아예 join을 빼버리는 방법도 있다.

Sort-Merge Join, Shuffle Hash Join을 써서 spill-safe하게 join할 수도 있다.

리니지

Persistence는 계산 비용을 줄여주는 것이고, checkpoint도 리니지 날려버림

아무튼 기본적으로는 데이터를 보고 파티셔닝하는 것을 최적화해야 함

Spark Web UI에서 peak exec mem같은 지표를 보고 판단하자.