티스토리 뷰

스파크

스파크 튜닝 관련 20230409

killog 2023. 4. 9. 22:50
반응형

intro

요즘 스파크 관련해서 빅데이터에 눌린 삶을 살고 있는데,, 스파크 튜닝에 대해 좀 더 자세히 알고자 이 글을 작성해보았습니다. 한달 정도 고통받고 있는 것 같은데, 스파크에 대한 고찰은 상당히 많이 하고 있는 것같아요.

이 글은 내가 언제 보게 되는것일까?

내 스파크 드라이버에서 제공하는 memory, executor 수의 최고점을 알게됐을때, 익스큐터가 더이상 작업 노동자로 보이지 않고, 통신노드로 보일때, 갑자기 spark 익스큐터가 자바이길 포기할때 보면된다. (TB 이상의 데이터를 사용한다면이라는 말과 동일하다.)

우선 우리는 바보가 아니기 때문에 넓은 기간의 데이터를 한 번에 처리하는 것이 아니라, 단기간의 데이터를 먼저 처리하는 것에 성공하고, 이후에 기간을 배수로 처리하고자 할 것이다. 이 짧은 기간의 데이터가 스파크의 리소스 한계와 부딛쳤을때 같이 고려하면된다.

넓은 기간의 데이터를 한 번에 처리하는 것이 아니라, 단기간의 데이터를 먼저 처리하는 것에 성공하고, 이후에 기간을 배수로 처리하고자 하자.

Spark cluster components

데이터를 다루기 전, 데이터 사이즈 + 사용 메모리 체크 + 처리 시간 체크 할 것

  1. 데이터 사이즈, 사용 메모리, 처리시간 체크가 왜 중요할까?
    1. 당연하겠지만 되던게 안되기때문이다.
    2. 너가 콧노래를 부르며 1만 건의 데이터를 처리할때는 전혀 문제가 없던 것이,비슷한 스펙 비슷한 처리여도 1만건의 데이터에서는 순식간에 해결되던것도 6만건에선 힘들 수 있고, 이게 하루 단위 작은 데이터 작업이 아니라 크게 백필이 필요한 경우, 스파크 전체 리소스를 눈치보면서 다 잡아먹어도 안될 수 있다 이말이다.
    3. 자 이번 프로젝트 비슷해요! 해서 당근 콧노래를 부르면서 룰루랄라 당근되겠지! 하고 들어갔다가 경기도 오산시 아니 되던게 왜 안돼! 하면서 익스큐터가 탈주하고 메모리는 계속 터지고 너를 당황시킨다면 데이터 사이즈, 메모리, 처리시간이 증가했기 때문일것이다. 사실상 이 글의 모든 문제의 원인이 아닐까..
  2. hdfs , linux 에서 데이터 사이즈 체크하기
    1. linux 데이터 사이즈 체크 : du
      1. du 명령어에서 자주 사용하는 옵션은 다음과 같다.
        • -h : 파일 크기를 보기 쉽게 사람이 읽기 쉬운 형식으로 출력.
        • -s : 디렉토리의 총 사용량만 출력
        • -c : 디렉토리의 총 사용량과 각 파일의 사용량을 출력
        • -k : 디스크 사용량을 1K 블록 단위로 출력
    # 디렉토리 사용량 확인
    git:(master) ✗ du -sh test/
    4.0K    test/
    
    # file 크기 체크 
    du -h test/myfile.txt
    4.0K    test/myfile.txt
  1. pure python 의 경우, python 의 memory_profiler 라이브러리 사용하기등으로 메모리 체크할수 있다. (psutil, tracemalloc,, )
    • memory_profiler 라이브러리 설치하기
pip install memory_profiler
Line #    Mem usage    Increment  Occurences   Line Contents
============================================================
     3   17.148 MiB   17.148 MiB           1   @profile
     4                                         def my_func():
     5   75.422 MiB    0.000 MiB           1       a = [1] * (10 ** 6)
     6  615.730 MiB  540.309 MiB           1       b = [2] * (2 * 10 ** 7)
     7   76.684 MiB -539.047 MiB           1       del b
     8   77.684 MiB    1.000 MiB           1       c = [3] * (10 ** 6)
     9   77.684 MiB    0.000 MiB           1       del c
    10   17.289 MiB  -60.395 MiB           1       return a
    1. pyspark 에서 메모리 측정
      1. 데이터 세트에 필요한 메모리 소비량의 크기를 결정하는 가장 좋은 방법은 RDD를 생성하고 캐시에 넣은 다음 웹 UI에서 "Storage" 페이지를 확인하는 것이다. 이 페이지는 RDD가 차지하는 메모리 양을 알려준다.
      2. 특정 객체의 메모리 사용량을 추정하려면 SizeEstimatorestimate방법을 사용해보는 것 또한 방법이다.
from pyspark.sql import SparkSession

# Create a SparkSession object
spark = SparkSession.builder.appName("MyApp").getOrCreate()

# Create a DataFrame
df = spark.read.format("csv").option("header", True).load("path/to/file.csv")

# Cache the DataFrame
df.cache()

# Do some operations on the DataFrame
df_filtered = df.filter(df.column_name == "some_value")
df_grouped = df_filtered.groupBy(df_filtered.column_name2).agg({"column_name3": "sum"})

# Unpersist the DataFrame
df.unpersist()
  from pyspark import SizeEstimator

  # Create a list of integers
  lst = [1, 2, 3, 4, 5]

  # Estimate the memory usage of the list
  mem = SizeEstimator.estimate(lst)

  # Convert to megabytes
  mem_mb = mem / 1024 / 1024

  print(f"Memory usage: {mem_mb} MB")

스파크의 task (=그럼 스파크는 익스큐터에 태스크를 할당 하는 단위가 어떻게 될까?)

Spark에서 task를 나누는 기준은 데이터의 파티션(partition)이다. 각각의 파티션은 독립적으로 처리될 수 있는 작은 데이터 조각이다. Spark은 데이터를 파티션 단위로 처리하여 분산처리를 수행한다.

다만, 이걸로 모든건 적합하지 않다. task 만 300개! 이렇게 돼있으면 내부 동작은 어떻게 아는가? 싶지만, dag 스케줄러에서 lazy 연산에 따라 "action" 함수 이전의 모든 작업들을 task 로 이해하고 자르기 때문에 좀더 dag 스케줄러의 액션 을 기준으로 작업을 모니터링 하면 쉬울 것 같다.

예를 들어 내가 1. a 작업 (메모리 많이 소요) 2. b 작업( 메모리 많이 소요) 하는 2개의 작업을 통해 결과를 내기 위해서는 1-2 를 동시에 최적화시키기 보다는 a 작업에서 액션 으로 해당 작업을 최적화 하고, b 를 이후에 처리하는 방법이 있을 수 있다.

스파크의 맵 파티션과 맵함수

일부 작업의 경우 mapPartiiton 이 map 함수보다 메모리 최적화의 도움을 줄 수 있다.

map() 변환 연산은 RDD의 각 요소에 지정된 함수를 적용하고 동일한 크기의 새 RDD를 반환한다.

mapPartition() 변환 연산은 RDD의 각 파티션에 대해 지정된 함수를 적용하며, 각 개별 요소에 대해 적용하는 것보다 비용이 큰 경우에는 더 나은 성능을 제공할 수 있다.mapPartition()의 이점은 데이터를 하나의 요소 단위가 아니라 일괄적으로 처리하므로 노드간 데이터 전송에 드는 오버헤드를 줄일 수 있다. 따라서, 데이터 크기가 크고 변환 함수가 계산에 비용이 많이 드는 경우에는 mapPartition()map()보다 더 효율적일 수 있습니다.

하지만, mapPartition()에는 몇 가지 제한사항이 있는데, 데이터가 파티션 사이에서 균등하게 분배되지 않는 경우 데이터 스큐가 발생할 수 있다. 또한, mapPartition()은 일괄 처리로 데이터를 처리하기 때문에 특정 사용 사례에서는 map()보다 더 많은 메모리를 요구할 수 있다.

Kryo 직렬화

https://github.com/EsotericSoftware/kryo

kryo 직렬화는 Java 객체 그래프를 직렬화하기 위한 빠르고 효율적인 직렬화 라이브러리 중 하나이다. 기본 직렬화 라이브러리인 Java Serialization보다 더 높은 성능을 제공한다. Kryo 직렬화를 사용하면 객체를 직렬화하고 역직렬화하는 데 걸리는 시간을 줄일 수 있으며, 메모리 사용량을 최적화할 수 있다. 또한, Kryo는 자동으로 클래스 등록을 처리하기 때문에 Java Serialization보다 더 편리하다.

spark-submit \
    --conf spark.serializer=org.apache.spark.serializer.KryoSerializer \
    myapp.py

Memory Management Overview

  • 스파크 메모리 설계
    • 스파크의 메모리 사용량은 크게 실행과 저장이라는 두 가지 범주 중 하나에 속한다.
    • 실행 메모리는
      • 셔플, 조인, 정렬 및 집계에서 계산에 사용되는 메모리를 의미
      • 실행은 필요한 경우 스토리지(저장)를 제거할 수 있다. 하지만, 총 스토리지 메모리 사용량이 특정 임계값(R) 아래로 떨어질 때까지만 실행됩니다. 즉, R은 캐시된 블록이 제거되지 않는 M 내의 하위 영역을 설명합니다.
      • 실행저장통합 영역(M)을 공유한다
      • 실행 메모리가 사용되지 않으면 스토리지(저장)는 사용 가능한 모든 메모리를 획득할 수 있으며 그 반대도 마찬가지입니다.
    • 스토리지 메모리는
      • 클러스터를 통해 내부 데이터를 캐싱하고 전파하는 데 사용되는 메모리를 의미합니다.
      • 실행저장통합 영역(M)을 공유한다
      • 실행 메모리가 사용되지 않으면 스토리지(저장)는 사용 가능한 모든 메모리를 획득할 수 있으며 그 반대도 마찬가지이다.
      • 스토리지는 구현의 복잡성으로 인해 실행을 제거하지 못할 수 있다.
  • 이 설계는 몇 가지 바람직한 특성을 보장하는데
    1. 캐싱을 사용하지 않는 애플리케이션은 전체 공간을 실행에 사용하여 불필요한 디스크 유출을 방지할 수 있다.
    2. 캐싱을 사용하는 애플리케이션은 데이터 블록이 제거되지 않는 최소 스토리지 공간(R)을 예약할 수 있습니다.
    3. 마지막으로, 이 접근 방식은 메모리가 내부적으로 어떻게 분할되는지에 대한 사용자의 전문 지식 없이도 다양한 워크로드에 대해 합리적인 즉시 사용 가능한 성능을 제공한다.
    => 생각할 점 : 캐싱을 사용하는 스파크 작업의 경우, 내가 모르는 내장 라이브러리의"R"의 메모리 사용량이 존재할 예정이다.
  • 두 가지 관련 구성이 있지만 기본값이 대부분의 워크로드에 적용되므로 일반 사용자는 이러한 구성을 조정할 필요가 없습니다:
    • spark.memory.fraction은 "M"(실행저장통합 영역(M)을 공유)의 크기를 (JVM 힙 공간 - 300MiB)(기본값 0.6)의 일부로 나타낸다. 나머지 공간(40%)은 사용자 데이터 구조, 스파크의 내부 메타데이터, 희소하고 비정상적으로 큰 레코드의 경우 OOM 오류로부터 보호하기 위해 예약된다.
      • => spark.memory.fraction의 값은 JVM의 old 세대 또는 "tenured" 세대 내에서 이 양의 힙 공간을 편안하게 맞추기 위해 설정되어야 한다. 자세한 내용은 아래 고급 GC 튜닝에 대한 설명을 참조/
    • spark.memory.storageFraction은 R(R은 캐시된 블록이 제거되지 않는 M 내의 하위 영역을)의 크기를 M의 분수(기본값 0.5)로 나타냅니다. R은 M 내의 저장 공간으로, 캐시된 블록이 실행에 의해 제거되는 것을 방지한다.

gc 와 gc timeout

Spark cluster components

Spark can efficiently support tasks as short as 200 ms, because it reuses one executor JVM across many tasks and it has a low task launching cost, so you can safely increase the level of parallelism to more than the number of cores in your clusters.(https://spark.apache.org/docs/latest/tuning.html#memory-usage-of-reduce-tasks)

이 말인 즉슨, 익스큐터 이놈 시키는 내가 1코어로 1 태스크만 시켰는데, gc 를 재깍재깍 바로 하지 않을수 있다는 말이다. 익스큐터 한놈당 일을 200개 맡기게가 내 한계 메모리 할당 지점인데, 200개하고 재깍재깍 메모리를 gc하지 않아 oome 가 발생한다면, 어느 부처님 개발자여도 화가 날 것이다. 물론 gc time 이 너무 길다고 에러가 나는 경우 또한 , 너그럽던 개발자도 화난 야차로 만들 수 있기때문에 우리는 gc 가 언제 발생하는지 체크를 해줘야한다.

(gc = 노동자들이 언제 리프레시를 하는지 체크. 월화수목금 일시켰는데 토일 리프레시 알아서 하고 월화수목금 일하길 바랬는데, 그렇지 않는 경우를 측정하자.)

Measuring the Impact of GC

이를 통해 Garbage Collection이 발생하는 빈도와 시간을 최적화하여 프로그램 성능을 향상시킬 수 있다.

-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

spark-submit \
--conf spark.executor.extraJavaOptions="-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedOops" \

Spark에서 GC 튜닝의 목표는 수명이 긴 RDD만 Old Generation에 저장하고 Young Generation은 수명이 짧은 개체를 저장할 수 있을 만큼 충분히 크기를 조정하는 것이다. 이렇게 하면 작업 실행 중에 생성된 임시 개체를 수집하기 위해 전체 GC를 피하는 데 도움이 됩니다. 유용할 수 있는 몇 가지 단계는 다음과 같다

  • 마이너 컬렉션이 너무 많고 메이저 GC가 많지 않은 경우 Eden에 더 많은 메모리를 할당하자!
  • GC 가 full 이라면, spark.memory.fraction 으로 캐시를 아예 줄이는 것도 ..
  • G1GC 가비지 컬렉터를 한번 시도해봐라! -XX:+UseG1GC gc 보틀넥 현상에서 효과가 있을 수 있다. -XX:G1HeapRegionSize 에서 G1 region 사이즈를 늘리는 것이 중요함.

G1(Garbage First)은 JDK 7부터 추가된 새로운 가비지 컬렉터입니다. G1은 전통적인 Mark-Sweep-Compact 알고리즘 대신에 가장 먼저 가비지가 발생한 영역(Garbage First)을 우선적으로 수집하는 방식으로 동작합니다.
G1은 전체 힙 공간을 여러 개의 작은 영역(G1 영역)으로 나눕니다. 각 영역은 Eden 영역, Survivor 영역, Old 영역 등으로 구성됩니다. G1은 Young GC와 Mixed GC로 구분되는 두 가지 타입의 가비지 컬렉션을 수행합니다.
Young GC는 Eden 영역과 Survivor 영역에서 발생한 가비지를 수집하는 가벼운 GC 작업입니다. Mixed GC는 Old 영역에서 발생한 가비지를 수집하는 더 무거운 GC 작업입니다. G1은 Young GC를 자주 수행하여 Old 영역에 가비지가 쌓이는 것을 예방합니다.
G1은 대용량 메모리에서 더욱 효과적으로 동작하며, 큰 힙 크기를 가진 서버 애플리케이션에 적합합니다. 또한, G1은 시스템 지연 시간을 최소화하면서 GC 작업을 수행할 수 있어 빠른 응답 시간이 필요한 애플리케이션에서도 사용할 수 있습니다. -> stop the world 가 적은듯

더 자세한 내용은 https://spark.apache.org/docs/latest/tuning.html#garbage-collection-tuning 여기를 참조하자.

브로드캐스트는 어떤 데이터를 쓰는 걸까?

Broadcasting Large Variables

https://spark.apache.org/docs/latest/tuning.html#broadcasting-large-variables

Using the broadcast functionality available in SparkContext can greatly reduce the size of each serialized task, and the cost of launching a job over a cluster. If your tasks use any large object from the driver program inside of them (e.g. a static lookup table), consider turning it into a broadcast variable. Spark prints the serialized size of each task on the master, so you can look at that to decide whether your tasks are too large; in general tasks larger than about 20 KiB are probably worth optimizing.

나는 여태까지 브로드캐스트에 작은 데이터만 올라간다고 생각했는데 이 망할놈의 스파크는 나한테 large 변수를 브로드캐스트하는 것을 튜닝이랍시고 알려주고 있는것일까 ? 라고 의심하면서 읽었지만, 내가 아는 내용과 거의 동일한 듯 보인다. 데이터 작업 중에 대-대 ,대-소 작업의 조인 등으로 비교 매칭 작업이있을때, 대-소 데이터 작업의 경우, 적극 브로드캐스트를 조인해봐라 라는 이야기로 보인다.

Heartbeat

Spark cluster components

  • heartbeat란 ?
    • 드라이버에게 익스큐터 heartbeat 를 보내야한다.
    • Spark에서는 드라이버와 각 익스큐터 사이의 통신을 유지하기 위해 Heartbeat라는 메커니즘이 사용되는데, 익스큐터는 주기적으로 드라이버에게 Heartbeat 메시지를 보내고, 드라이버는 응답을 반환한다. 이를 통해 Spark는 익스큐터의 상태를 추적하고 문제가 발생하는 경우 해당 익스큐터를 다시 시작할 수 있다.Heartbeat 오류가 발생하는 경우, Spark는 일부 익스큐터가 실패했다고 판단하고 해당 익스큐터를 다시 시작합니다. 따라서 Heartbeat 오류는 익스큐터의 재시작을 초래할 수 있습니다.
      • Spark에서 Heartbeat 주기는 spark.executor.heartbeatInterval 설정으로 지정되는데, 기본값은 10초/
        • spark-submit --conf spark.executor.heartbeatInterval=200s myapp.py
    • 일반적으로, Heartbeat 오류를 해결하려면 익스큐터와 드라이버 간의 네트워크 연결을 검사하고, 네트워크 문제를 해결하고 메모리 부족 문제를 해결해야 합니다. 또한, Spark 설정을 변경하여 Heartbeat 주기를 조정할 수 있다.
    • Heartbeat 메커니즘은 Spark의 안정성과 신뢰성을 유지하는 데 중요한 역할을 하지만, 때로는 Heartbeat이 실패할 수 있습니다. 이는 네트워크 문제, 익스큐터 장애, 메모리 부족 등 다양한 이유로 발생할 수 있다.
    • Spark cluster components

익스큐터 코어수와 메모리

  • 익스큐터 코어 수를 늘리는 경우, 1개의 익스큐터가 코어*익스큐터 개수 배수 만큼의 태스크를 처리하게된다. (데이터가 적어서 1개 코어로 여러 태스크에 작동하는 것 고려 x ) => 이것은 태스크 작업을 빠르게 처리하는 것처럼 보일 수 있지만, 한 익스큐터 내에서 같은 메모리 공간을 이용하고 있기때문에, oome 에 시달리고 있다면 좋은 선택이 아닐 수 있다.

셔플과 리파티션

    • 스파크 파티션
Spark의 DataFrame은 RDD와 유사하지만, 스키마 정보가 포함된 분산 데이터 집합이다. DataFrame은 행(row)과 열(column)을 가지며, 각 행은 여러 개의 열을 포함한다.

DataFrame은 파티션 개수를 조절하여 데이터 처리 성능을 최적화할 수 있다. 파티션 개수를 늘리면 데이터 처리 속도가 향상될 수 있지만, 파티션 개수가 너무 많으면 메모리 사용량이 증가하여 성능이 저하될 수 있다. 파티션 개수는 `repartition()` 메서드나 `coalesce()` 메서드를 사용하여 조절할 수 있다.

RDD와 DataFrame의 차이점 중 하나는 파티션 단위의 처리 방식이다. RDD는 파티션 단위로 처리되므로 각 파티션에서 연산이 수행되고, 결과를 병합하여 최종 결과를 생성한다. 반면에, DataFrame은 각 열에서 연산이 수행되므로 각 파티션에서 모든 행에 대해 동일한 연산이 수행된다.

따라서, DataFrame에서 파티션 개수를 조절할 때는 각 파티션에 대해 수행되는 연산의 특성을 고려해야 합니다. 연산이 CPU나 메모리 부족인 경우에는 파티션 개수를 늘리는 것이 좋을 수 있지만,  I/O 만 겁나 오래 걸리는 경우에는 파티션 개수를 줄이는 것이 효과적일 수 있다.
  • 리파티션은 하나의 익스큐터가 처리해야할 데이터 양의 리밸런싱을 도와주기 때문에 하나의 태스크가 처리해야할 작업의 시간, 메모리가 클수록, 리파티션을 통해 파티션의 개수를 늘리는 것이 좋다.
  • 리파티션이 그나마 데이터 개수를 익스큐터당 고르게 분배하는 방법이라 할 수 있지만, 로깅해보고 그렇지 않는 경우, 좀더 고민해보는 것도..
  • 하지만 그와 동시에 , 셔플 개수가 늘어나는 경우, 셔플 write 하는 과정에서 메모리가 터질 수 있으니, 실험과 스파크 ui 모니터링을 통해 적절한 값을 결정해야한다.
  • spark.default.parallelism 속성을 이용해 spark 의 디폴트 파티션 개수를 지정 가능하다.
    • 디폴트 : total core*3

data locality

데이터 지역성은 스파크 작업의 성능에 큰 영향을 미칠 수 있다. "데이터"와 "데이터에서 작동하는 코드"가 함께 있으면 계산이 빠른 경향이 있다. 그러나 코드와 데이터가 분리되면 둘 중 하나는 다른 하나로 이동해야되는데, 일반적으로 코드 크기가 데이터보다 훨씬 작기 때문에 데이터 덩어리보다 직렬화된 코드를 이곳저곳으로 보내는 것이 더 빠르다. 스파크는 이 일반적인 데이터 위치 원칙을 기반으로 스케줄링을 구축한다.

데이터 지역성은 데이터가 그것을 처리하는 코드에 얼마나 가까운지를 말한다. 데이터의 현재 위치를 기준으로 여러 수준의 지역성이 있습니다. 가장 가까운 순서에서 가장 먼 순서로:

  • PROCESS_LOCAL : 데이터는 실행 중인 코드와 동일한 JVM에 있습니다. 이게 가장 베스트다
  • NODE_LOCAL : 데이터는 동일한 노드에 있다. 동일한 노드의 HDFS 또는 동일한 노드의 다른 executor에 있을 수 있다.이것은 데이터가 프로세스 사이를 이동해야 하기 때문에 PROCESS_LOCAL 보다 약간 느리다.
  • NO_PREF : 데이터는 어디에서나 동일하게 신속하게 액세스되며 지역 선호도가 없습니다.
  • RACK_LOCAL : 데이터는 동일한 서버 랙에 있습니다. 데이터는 동일한 랙의 다른 서버에 있으므로 일반적으로 단일 스위치를 통해 네트워크를 통해 전송되어야 합니다.
  • ANY : 데이터가 네트워크의 다른 곳에 있고 동일한 랙에 있지 않다.

스파크는 모든 작업을 최적의 지역성 수준으로 예약하는 것을 선호하지만 항상 가능한 것은 아니다. 유휴 executor에 처리되지 않은 데이터가 없는 경우 스파크는 낮은 인접성 수준으로 전환된다.
a) 사용 중인 CPU가 같은 서버의 데이터에 대한 작업을 시작할 때까지 기다리거나, (spark.locality 파라미터)
b) 데이터를 이동해야 하는 더 먼 곳에서 즉시 새 작업을 시작하는
두 가지 옵션이 있다.

https://spark.apache.org/docs/latest/configuration.html#scheduling

Property Name Default Meaning Since Version
spark.locality.wait 3s 데이터 로컬 작업을 포기하고 덜 로컬 노드에서 시작하기 전에 데이터 로컬 작업을 시작하기까지 대기하는 시간. 동일한 대기가 여러 지역 수준(프로세스-로컬, 노드-로컬, 랙-로컬 등)을 거치는 데 사용된다.  각 레벨의 대기 시간을 사용자 지정할 수도 있습니다 spark.locality.wait.node. 작업이 길고 지역성이 좋지 않은 경우 이 설정을 늘려야 하지만 일반적으로 기본값이 잘 작동한다 0.5.0
spark.locality.wait.node spark.locality.wait Customize the locality wait for node locality. For example, you can set this to 0 to skip node locality and search immediately for rack locality (if your cluster has rack information). 0.8.0
spark.locality.wait.process spark.locality.wait Customize the locality wait for process locality. This affects tasks that attempt to access cached data in a particular executor process. 0.8.0
spark.locality.wait.rack spark.locality.wait Customize the locality wait for rack locality. 0.8.0
spark.scheduler.maxRegisteredResourcesWaitingTime      

참고 문헌

https://spark.apache.org/docs/latest/tuning.html#memory-usage-of-reduce-tasks

https://d2.naver.com/helloworld/1329

반응형

'스파크' 카테고리의 다른 글

Spark Join전략과 hint  (5) 2022.09.25
Spark Dataset 개념과 이해  (0) 2022.07.24
Spark: Cluster Computing with Working Sets 정리(해석)  (0) 2022.05.22
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함