如何在spark中有效地分配和使用分区?

时间:2017-03-27 06:00:48

标签: apache-spark load-balancing rdd partitioning wise

这是我的榜样。

val arr = Array((1,2), (1,3), (1,4), (2,3), (4,5))
val data = sc.parallelize(arr, 5)

data.glom.map(_length).collect
Array[Int] = Array(1, 1, 1, 1, 1)

val agg = data.reduceByKey(_+_)
agg.glom.map(_.length).collect
Array[Int] = Array(0, 1, 1, 0, 1)

val fil = agg.filter(_._2 < 4)
fil.glom.map(_.length).collect
Array[Int] = Array(0, 0, 1, 0, 0)

val sub = data.map{case(x,y) => (x, (x,y))}.subtractByKey(fil).map(_._2)
Array[(Int, Int)] = Array((1,4), (1,3), (1,2), (4,5))

sub.glom.map(_.length).collect
Array[Int] = Array(0, 3, 0, 0, 1)

我想知道的是均匀分配分区。

data变量由五个分区组成,所有数据均匀分区。

ex)par1: (1,2)
   par2: (1,3)
   par3: (1,4)
   par4: (2,3)
   par5: (4,5)

在几个transformation operation之后,仅使用分配给sub变量的五个分区中的两个。

sub变量由五个分区组成,但并非所有数据都是均匀分区的。

ex)par1: empty
   par2: (1,2),(1,3),(1,4)
   par3: empty
   par4: empty
   par5: (4,5)

如果我向transformation operation变量添加另一个sub,则会有5个可用分区,但只有2个分区将用于该操作。

ex)sub.map{case(x,y) => (x, x, (x,y))}

所以我想在操作数据时使用所有可用的分区。

我使用repartition方法,但它并不便宜。

ex) sub.repartition(5).glom.map(_.length).collect
Array[Int] = Array(0, 1, 1, 2, 0)

所以我正在寻找一种利用尽可能多的分区的明智方法。

有好办法吗?

1 个答案:

答案 0 :(得分:2)

所以repartition绝对是要走的路:)

你的例子有点太简单了,无法展示任何东西,因为Spark是为处理数十亿行而不是5行而构建的。 repartition不会将完全相同数量的行放入每个分区,但它会均匀地分配数据。尝试使用1.000.000行重做您的示例,您将看到数据确实在repartition之后均匀分布。

在处理大量数据转换时,数据偏差通常是一个大问题,而重新分区数据确实会带来额外时间的成本,因为它需要随机播放数据。虽然有时值得采取惩罚,因为它将使以下转型阶段运行得更快。