스파크-repartition () vs coalesce ()


254

Learning Spark에 따르면

데이터를 다시 파티션하는 것은 비용이 많이 드는 작업입니다. 또한 Spark에는 최적화 된 버전의 repartition()호출 coalesce()이있어 데이터 이동을 피할 수 있지만 RDD 파티션 수를 줄이는 경우에만 가능합니다.

내가 얻는 한 가지 차이점 repartition()은 파티션 수를 늘리거나 줄일 coalesce()수 있지만 파티션 수를 줄이면 줄일 수 있다는 것입니다.

파티션이 여러 시스템에 분산되어 coalesce()실행되는 경우 어떻게 데이터 이동을 피할 수 있습니까?

답변:


354

전체 셔플을 피합니다 . 숫자가 줄어드는 것으로 알려진 경우 실행 프로그램은 최소 수의 파티션에 데이터를 안전하게 보관할 수 있으며 추가 노드에서 데이터를 우리가 유지 한 노드로만 이동할 수 있습니다.

따라서 다음과 같이 진행됩니다.

Node 1 = 1,2,3
Node 2 = 4,5,6
Node 3 = 7,8,9
Node 4 = 10,11,12

그런 다음 coalesce2 개의 파티션으로 줄입니다.

Node 1 = 1,2,3 + (10,11,12)
Node 3 = 7,8,9 + (4,5,6)

노드 1과 노드 3은 원래 데이터를 이동할 필요가 없었습니다.


115
답변 주셔서 감사합니다. 문서 minimize data movement대신에 더 잘 말해야합니다 avoiding data movement.
Praveen Sripati

12
repartition대신 사용해야 할 경우 가 coalesce있습니까?
Niemand

21
: @Niemand 나는 현재 문서 커버 꽤 잘 생각 github.com/apache/spark/blob/... 모든 것을 명심 repartition호출입니다 않는 coalesceshuffletrue로 매개 변수를 설정합니다. 도움이되는지 알려주세요.
저스틴 피 호니

2
기존 파티션 파일 수를 줄일 수 있습니까? hdfs는 없지만 많은 파일에 문제가 있습니다.

2
재분할이 줄어들고 있다는 것을 모르기 때문에 통계적으로 느리게 진행될 것입니다. 내부적으로 그것은 단지 shuffle = true깃발 과 합병이라고 부릅니다
Justin Pihony

172

저스틴의 대답은 대단하고이 반응은 더 깊이 들어가게됩니다.

repartition알고리즘은 전체 셔플을 수행하고 고르게 분산 된 데이터로 새 파티션을 만듭니다. 1에서 12까지의 숫자로 DataFrame을 만듭니다.

val x = (1 to 12).toList
val numbersDf = x.toDF("number")

numbersDf 내 컴퓨터에 4 개의 파티션이 있습니다.

numbersDf.rdd.partitions.size // => 4

파티션에서 데이터를 나누는 방법은 다음과 같습니다.

Partition 00000: 1, 2, 3
Partition 00001: 4, 5, 6
Partition 00002: 7, 8, 9
Partition 00003: 10, 11, 12

repartition방법 으로 전체 셔플을 수행하고 두 노드에서이 데이터를 가져 오 겠습니다 .

val numbersDfR = numbersDf.repartition(2)

numbersDfR내 컴퓨터 에서 데이터가 분할되는 방법은 다음과 같습니다 .

Partition A: 1, 3, 4, 6, 7, 9, 10, 12
Partition B: 2, 5, 8, 11

repartition방법을 사용하면 새 파티션을 만들고 새 파티션에 데이터를 균등하게 분배 할 수 있습니다 (데이터 분배는 더 큰 데이터 세트에 대해 더 균일합니다).

차이 사이 coalescerepartition

coalesce기존 파티션을 사용하여 섞은 데이터 양을 최소화합니다. repartition새 파티션을 만들고 전체 셔플을 수행합니다. coalesce데이터 양이 다른 파티션 (때로는 크기가 다른 파티션)을 생성하고 크기 repartition가 거의 같은 파티션을 생성합니다.

인가 coalesce또는 repartition빠른?

coalesce보다 빠른 실행이 가능 repartition하지만 크기가 다른 파티션은 일반적으로 같은 크기의 파티션보다 작동 속도가 느립니다. 일반적으로 큰 데이터 세트를 필터링 한 후 데이터 세트를 다시 파티셔닝해야합니다. 내가 발견 한 repartition스파크가 동일한 크기의 파티션 작업에 내장되어 있기 때문에 빠른 전체로.

주의 : 재 파티션으로 인해 디스크의 데이터 크기가 증가 할 수 있다는 것이 궁금 합니다. 대규모 데이터 세트에서 재 파티셔닝 / 연합을 사용할 때 테스트를 실행하십시오.

더 자세한 내용을 원하시면 이 블로그 게시물을 읽으십시오 .

실제로 통합 및 재 파티셔닝을 사용할 때


8
훌륭한 답변 @Powers, 그러나 파티션 A와 B의 데이터가 왜곡되지 않습니까? 균등하게 분배되는 방법은 무엇입니까?
anwartheravian

또한 OOM 오류없이 파티션 크기를 얻는 가장 좋은 방법은 무엇입니까? 사용 rdd.glom().map(len).collect()하지만 많은 OOM 오류가 발생합니다.
anwartheravian

8
@anwartheravian- repartition알고리즘이 매우 작은 데이터 세트에 대해 데이터를 동일하게 분배하지 않기 때문에 파티션 A와 파티션 B의 크기가 다릅니다 . 나는 repartition5 백만 개의 레코드를 13 개의 파티션으로 구성하고 각 파일은 89.3MB와 89.6MB 사이였습니다.
Powers

1
@이 기능은 세부적으로 더 잘 보입니다.
Green

1
이것은 차이점을 훨씬 더 잘 설명합니다. 감사!
Abhi

22

여기서 주목할 점은 Spark RDD의 기본 원칙이 불변성이라는 것입니다. 재 파티션 또는 병합으로 새로운 RDD가 생성됩니다. 기본 RDD는 원래 파티션 수로 계속 존재합니다. 사용 사례가 캐시에서 RDD를 유지해야하는 경우 새로 작성된 RDD에 대해서도 동일하게 수행해야합니다.

scala> pairMrkt.repartition(10)
res16: org.apache.spark.rdd.RDD[(String, Array[String])] =MapPartitionsRDD[11] at repartition at <console>:26

scala> res16.partitions.length
res17: Int = 10

scala>  pairMrkt.partitions.length
res20: Int = 2

좋은 것! 이것은 중요하고 최소한이 경험이 풍부한 스칼라 개발에있어 명백하지는 않습니다. 즉, 데이터를 수정 하거나 파티션을 통합 하려는 시도가 아니라 노드 전체에 데이터가 분산되는 방식
doug

1
@Harikrishnan 그래서 합병의 경우 다른 답변을 올바르게 이해하면 Spark는 기존 파티션을 사용하지만 RDD는 불변이므로 Coalesce가 기존 파티션을 어떻게 사용하는지 설명 할 수 있습니까? 내 이해에 따라 Spark는 병합 된 기존 파티션에 새 파티션을 추가한다고 생각했습니다.
Explorer

그러나 "구형"RDD가 더 이상 실행 그래프에 알려진대로 사용되지 않으면 지속되지 않으면 메모리에서 지워집니다.
Markus

15

repartition -모든 데이터를 섞기 때문에 파티션 수를 늘리면서 사용하는 것이 좋습니다.

coalesce-파티션 수를 줄이면서 사용하는 것이 좋습니다. 예를 들어 3 개의 파티션이 있고이를 2로 줄이려면 coalesce세 번째 파티션 데이터를 파티션 1과 2로 이동합니다. 파티션 1과 2는 동일한 컨테이너에 남아 있습니다. 반면, repartition모든 파티션에서 데이터를 섞으면 실행기 간의 네트워크 사용량이 높아져 성능에 영향을 미칩니다.

coalescerepartition파티션 수를 줄이는 동안 보다 성능이 우수 합니다.


유용한 설명.
Narendra Maru

11

무엇에서 다음 코드 와 코드 워드 프로세서 것은 즉 coalesce(n)과 동일 coalesce(n, shuffle = false)repartition(n)동일하다coalesce(n, shuffle = true)

따라서 coalescerepartition파티션 수를 늘리는 데 사용할 수 있습니다.

을 사용하면 shuffle = true실제로 더 많은 파티션으로 통합 할 수 있습니다. 이것은 소수의 파티션이 비정상적으로 클 수있는 소수의 파티션 (예 : 100)이있는 경우에 유용합니다.

강조해야 할 또 다른 중요한 참고 사항 은 파티션 수 를 크게 줄이면 셔플 버전 coalesce( repartition이 경우 와 동일) 을 사용하는 것이 좋습니다. 이렇게하면 부모 파티션 (여러 작업) 에서 계산 을 병렬 로 수행 할 수 있습니다 .

그러나 과도하게 병합을 수행하는 경우 numPartitions = 1(예 :의 경우 하나의 노드) 원하는 노드보다 적은 수의 노드에서 계산이 수행 될 수 있습니다 numPartitions = 1. 이를 피하기 위해을 전달할 수 있습니다 shuffle = true. 이렇게하면 셔플 단계가 추가되지만 현재 업스트림 파티션이 병렬로 실행됩니다 (현재 파티션이 무엇이든간에).

여기 에서 관련 답변을 참조 하십시오


10

모든 답변은이 자주 묻는 질문에 훌륭한 지식을 추가하고 있습니다.

이 질문의 타임 라인의 전통에 따라 여기 2 센트가 있습니다.

매우 특별한 경우에, repartition이 coalesce보다 빠르다는 것을 알았습니다 .

내 응용 프로그램에서 우리가 추정하는 파일 수가 특정 임계 값보다 적을 때 재 파티션이 더 빨리 작동합니다.

여기 내가 무슨 뜻인지

if(numFiles > 20)
    df.coalesce(numFiles).write.mode(SaveMode.Overwrite).parquet(dest)
else
    df.repartition(numFiles).write.mode(SaveMode.Overwrite).parquet(dest)

위의 스 니펫에서 파일이 20 미만인 경우 병합이 끝나는 데 시간이 오래 걸리고 파티션이 훨씬 빠르며 위의 코드가되었습니다.

물론이 숫자 (20)는 작업자 수와 데이터 양에 따라 다릅니다.

희망이 도움이됩니다.


6

다시 파티션 : 데이터를 새로운 수의 파티션으로 섞습니다.

예 : 초기 데이터 프레임은 200 개의 파티션으로 분할됩니다.

df.repartition(500): 200 개의 파티션에서 새로운 500 개의 파티션으로 데이터가 섞입니다.

Coalesce : 기존 파티션 수로 데이터를 섞습니다 .

df.coalesce(5): 나머지 195 개의 파티션에서 5 개의 기존 파티션으로 데이터가 섞입니다.


4

저스틴과 파워의 대답에 추가하고 싶습니다-

repartition기존 파티션을 무시하고 새 파티션을 만듭니다. 따라서 데이터 왜곡을 수정하는 데 사용할 수 있습니다. 분배를 정의하기 위해 파티션 키를 언급 할 수 있습니다. 데이터 스큐는 '빅 데이터'문제 공간에서 가장 큰 문제 중 하나입니다.

coalesce기존 파티션에서 작동하고 서브 세트를 섞습니다. 데이터 비뚤어 짐을 수정 repartition하지는 못합니다. 따라서 가격이 저렴하더라도 필요한 것이 아닐 수도 있습니다.


3

모든 훌륭한 답변 repartition에 데이터 병렬화를 활용하는 가장 좋은 옵션 중 하나 를 추가하고 싶습니다 . coalesce파티션을 줄이는 저렴한 옵션을 제공 하지만 HDFS 또는 다른 싱크에 데이터를 쓸 때 큰 쓰기를 활용하는 데 매우 유용합니다.

나는 이것을 최대한 활용하기 위해 마루 형식으로 데이터를 쓸 때 유용하다는 것을 알았습니다.


2

PySpark (AWS EMR)에서 단일 csv 파일을 출력으로 생성하고 s3에 저장하는 데 문제가있는 사람은 재 파티셔닝을 사용하여 도움을 받았습니다. 그 이유는 유일하게 전체 셔플을 수행 할 수 없지만 재분할은 가능합니다. 기본적으로 재 파티셔닝을 사용하여 파티션 수를 늘리거나 줄일 수 있지만 병합을 사용하여 파티션 수 (1은 아님) 만 줄일 수 있습니다. 다음은 AWS EMR에서 s3으로 CSV를 작성하려는 사람을위한 코드입니다.

df.repartition(1).write.format('csv')\
.option("path", "s3a://my.bucket.name/location")\
.save(header = 'true')

0

간단한 방법으로 COALESCE :-는 파티션 수를 줄이기위한 것입니다. 데이터를 섞지 않고 파티션을 압축합니다.

반복 :-파티션의 수를 늘리고 줄일 수 있지만 셔플 링이 발생합니다.

예:-

val rdd = sc.textFile("path",7)
rdd.repartition(10)
rdd.repartition(2)

둘 다 잘 작동합니다

그러나 우리는 일반적으로 하나의 클러스터에서 출력을 볼 필요가있을 때이 두 가지를 수행합니다.


9
Coalese와의 데이터 이동도있을 것입니다.
sun_dare

0

그러나 대규모 데이터를 처리하는 경우 통합 노드에 제공되는 데이터가 고도로 구성되어 있는지 확인해야합니다. 모든 데이터가 해당 노드에로드되므로 메모리 예외가 발생할 수 있습니다. 배상은 비용이 많이 들지만 사용하는 것을 선호합니다. 데이터를 셔플하고 균등하게 분배하기 때문입니다.

합체와 재분할 중에서 선택하는 것이 현명합니다.


0

repartition알고리즘은 전체 데이터 셔플을 수행하고 데이터를 동일 크기의 파티션을 생성한다. coalesce전체 파티션을 피하기 위해 기존 파티션을 결합합니다.

Coalesce는 많은 파티션으로 RDD를 수행하고 단일 작업자 노드에서 파티션을 결합하여 더 적은 파티션으로 최종 RDD를 생성하는 데 효과적입니다.

Repartition요청한 최종 파티션 수를 생성하기 위해 RDD의 데이터를 다시 섞습니다. DataFrame의 파티셔닝은 프레임 워크에서 관리해야하는 낮은 수준의 구현 세부 사항처럼 보이지만 그렇지 않습니다. 큰 DataFrame을 작은 것으로 필터링 할 때는 거의 항상 데이터를 다시 분할해야합니다. 큰 DataFrame을 자주 작은 DataFrame으로 필터링하므로 파티션을 다시 나누는 데 익숙해집니다.

더 자세한 내용을 원하시면 이 블로그 게시물을 읽으십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.