Spark - repartition() vs coalesce()
по данным обучения Spark
имейте в виду, что перераспределение ваших данных является достаточно дорогостоящей операцией. Spark также имеет оптимизированную версию repartition (), называемую coalesce (), которая позволяет избежать перемещения данных, но только если вы уменьшаете количество разделов RDD.
одно отличие, которое я получаю, заключается в том, что с помощью repartition () количество разделов может быть увеличено/ уменьшено, но с coalesce () количество разделов может быть только уменьшившийся.
Если разделы распределены по нескольким машинам и выполняется coalesce (), как можно избежать перемещения данных?
7 ответов
настоящее полное перемешать. Если известно, что число уменьшается, исполнитель может безопасно хранить данные о минимальном количестве разделов, перемещая данные только с дополнительных узлов на узлы, которые мы сохранили.
Итак, это будет что-то вроде этого:
Node 1 = 1,2,3
Node 2 = 4,5,6
Node 3 = 7,8,9
Node 4 = 10,11,12
затем coalesce
до 2 разделов:
Node 1 = 1,2,3 + (10,11,12)
Node 3 = 7,8,9 + (4,5,6)
обратите внимание, что узел 1 и узел 3 не требовали перемещения исходных данных.
ответ Джастина потрясающий, и этот ответ идет более глубоко.
на repartition
алгоритм выполняет полную перетасовку и создает новые разделы с равномерно распределенными данными. Давайте создадим фрейм данных с числами от 1 до 12.
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
метод создает новые разделы и равномерно распределяет данные в новых разделах (распределение данных больше даже для больших наборов данных).
разницу между coalesce
и repartition
coalesce
использует существующие разделы, чтобы минимизировать объем данных, которые тасуются. repartition
создает новые разделы и делает полный shuffle. coalesce
приводит к разделам с разными объемами данных (иногда разделы, которые имеют разные размеры) и repartition
приводит к примерно равным по размеру разделам.
Is coalesce
или repartition
быстрее?
coalesce
может работать быстрее, чем repartition
, но неравные по размеру разделы, как правило, работают медленнее, чем равные по размеру разделы. Обычно нужно переразметить данных после фильтрации большие наборы данных. Я нашел repartition
быть быстрее в целом, потому что Spark построен для работы с разделами одинакового размера.
читать этот блог если вы хотите еще более детально.
еще один момент, который следует отметить здесь, заключается в том, что основным принципом 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
все ответы добавляют некоторые большие знания в этот очень часто задаваемый вопрос.
Итак, следуя традиции временной шкалы этого вопроса, вот мои 2 цента.
нашел передел будет быстрее срастаться в очень конкретном случае.
в моем приложении, когда количество файлов, которое мы оцениваем, ниже определенного порога, перераспределение работает быстрее.
вот что я имею в виду
if(numFiles > 20)
df.coalesce(numFiles).write.mode(SaveMode.Overwrite).parquet(dest)
else
df.repartition(numFiles).write.mode(SaveMode.Overwrite).parquet(dest)
в приведенном выше фрагменте, если мои файлы были меньше 20, coalesce принимал навсегда, чтобы закончить, в то время как переделка была намного быстрее, и поэтому приведенный выше код.
конечно, эта цифра (20) будет зависеть от количества работников и объема данных.
надеюсь, что это поможет.
простым способом COALESCE : - только для уменьшения нет разделов, нет перетасовки данных он просто сжимает разделы
REPARTITION: - для увеличения и уменьшения нет разделов, но происходит перетасовка
пример:
val rdd = sc.textFile("path",7)
rdd.repartition(10)
rdd.repartition(2)
Как работает
но мы обычно идем на эти две вещи, когда нам нужно увидеть результат в одном кластере, мы идем с этим.
но также вы должны убедиться, что данные, которые приходят объединяются узлы должны быть высоко настроены, если вы имеете дело с огромными данными. Поскольку все данные будут загружены на эти узлы, может привести к исключению памяти. Хотя возмещение и дорого, я предпочитаю его использовать. Так как он перемешивает и распределяет данные поровну.
будьте мудры, чтобы выбрать между объединением и переделом.
repartition-рекомендуется использовать repartition при увеличении без разделов, поскольку это связано с перетасовкой всех данных.
coalesce-рекомендуется использовать coalesce при уменьшении нет разделов. Например, если у вас есть 3 раздела, и вы хотите уменьшить его до 2 разделов, Coalesce переместит данные 3-го раздела В разделы 1 и 2. Разделы 1 и 2 останутся в одном контейнере.но repartition перетасует данные во всех разделах, поэтому использование сети между исполнителем будет высокий, и это влияет на производительность.
производительность мудрая объединяет производительность лучше, чем передел, не уменьшая при этом никаких разделов.