这是我的榜样。
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)
所以我正在寻找一种利用尽可能多的分区的明智方法。
有好办法吗?
答案 0 :(得分:2)
所以repartition
绝对是要走的路:)
你的例子有点太简单了,无法展示任何东西,因为Spark是为处理数十亿行而不是5行而构建的。 repartition
不会将完全相同数量的行放入每个分区,但它会均匀地分配数据。尝试使用1.000.000行重做您的示例,您将看到数据确实在repartition
之后均匀分布。
在处理大量数据转换时,数据偏差通常是一个大问题,而重新分区数据确实会带来额外时间的成本,因为它需要随机播放数据。虽然有时值得采取惩罚,因为它将使以下转型阶段运行得更快。