Apache spark 以独占方式按键启动RDD分区

Apache spark 以独占方式按键启动RDD分区,apache-spark,pyspark,rdd,Apache Spark,Pyspark,Rdd,我希望按键对RDD进行分区,并确保每个分区只包含单个键的值。例如,如果我有100个不同的键值和I重新分区(102),RDD应该有2个空分区和100个分区,每个分区包含一个键值 我尝试了groupByKey(k).repartition(102),但这并不能保证每个分区中一个键的排他性,因为我看到一些分区包含一个键的更多值和两个以上的空值 标准API中有没有办法做到这一点?对于RDD,您是否尝试过使用按键对RDD进行分区,如中所示?如果需要,可以将分区数指定为清除空分区的键数 在Dataset A

我希望按键对RDD进行分区,并确保每个分区只包含单个键的值。例如,如果我有100个不同的键值和I
重新分区(102)
,RDD应该有2个空分区和100个分区,每个分区包含一个键值

我尝试了
groupByKey(k).repartition(102)
,但这并不能保证每个分区中一个键的排他性,因为我看到一些分区包含一个键的更多值和两个以上的空值


标准API中有没有办法做到这一点?

对于RDD,您是否尝试过使用按键对RDD进行分区,如中所示?如果需要,可以将分区数指定为清除空分区的键数

在Dataset API中,您可以使用with a
作为按该列中的值进行分区的参数(不过请注意,这使用
spark.sql.shuffle.partitions
作为分区数,因此将得到更多的空分区)。

要使用partitionBy()RDD,必须由元组(对)对象组成。下面是一个例子:

假设我有一个包含以下数据的输入文件:

OrderId|OrderItem|OrderDate|OrderPrice|ItemQuantity
1|Gas|2018-01-17|1895|1
1|Air Conditioners|2018-01-28|19000|3
1|Television|2018-01-11|45000|2
2|Gas|2018-01-17|1895|1
2|Air Conditioners|2017-01-28|19000|3
2|Gas|2016-01-17|2300|1
1|Bottle|2018-03-24|45|10
1|Cooking oil|2018-04-22|100|3
3|Inverter|2015-11-02|29000|1
3|Gas|2014-01-09|2300|1
3|Television|2018-01-17|45000|2
4|Gas|2018-01-17|2300|1
4|Television$$|2018-01-17|45000|2
5|Medicine|2016-03-14|23.50|8
5|Cough Syrup|2016-01-28|190|1
5|Ice Cream|2014-09-23|300|7
5|Pasta|2015-06-30|65|2

PATH_TO_FILE="file:///u/vikrant/OrderInputFile"
将文件读入RDD并跳过标题

RDD = sc.textFile(PATH_TO_FILE)
header=RDD.first();
newRDD = RDD.filter(lambda x:x != header)
现在让我们将RDD重新划分为“5”个分区

partitionRDD = newRDD.repartition(5)
print("Partitions structure: {}".format(partitionRDD.glom().collect()))
让我们看看数据是如何分布在这些“5”分区中的

partitionRDD = newRDD.repartition(5)
print("Partitions structure: {}".format(partitionRDD.glom().collect()))
在这里,您可以看到数据被写入两个分区,其中三个分区是空的,并且数据分布不均匀

Partitions structure: [[], 
[u'1|Gas|2018-01-17|1895|1', u'1|Air Conditioners|2018-01-28|19000|3', u'1|Television|2018-01-11|45000|2', u'2|Gas|2018-01-17|1895|1', u'2|Air Conditioners|2017-01-28|19000|3', u'2|Gas|2016-01-17|2300|1', u'1|Bottle|2018-03-24|45|10', u'1|Cooking oil|2018-04-22|100|3', u'3|Inverter|2015-11-02|29000|1', u'3|Gas|2014-01-09|2300|1'], 
[u'3|Television|2018-01-17|45000|2', u'4|Gas|2018-01-17|2300|1', u'4|Television$$|2018-01-17|45000|2', u'5|Medicine|2016-03-14|23.50|8', u'5|Cough Syrup|2016-01-28|190|1', u'5|Ice Cream|2014-09-23|300|7', u'5|Pasta|2015-06-30|65|2'], 
[], []]
我们需要创建一对RDD,以便RDD数据均匀分布在多个分区中。 让我们创建一对RDD并将其分解为键值对

pairRDD = newRDD.map(lambda x :(x[0],x[1:]))
现在,让我们将此rdd重新划分为“5”分区,并使用第[0]位的键将数据统一分布到分区中

newpairRDD = pairRDD.partitionBy(5,lambda k: int(k[0]))
现在我们可以看到,数据是根据匹配的键值对均匀分布的

print("Partitions structure: {}".format(newpairRDD.glom().collect()))
Partitions structure: [
[(u'5', u'|Medicine|2016-03-14|23.50|8'), 
(u'5', u'|Cough Syrup|2016-01-28|190|1'), 
(u'5', u'|Ice Cream|2014-09-23|300|7'), 
(u'5', u'|Pasta|2015-06-30|65|2')],

[(u'1', u'|Gas|2018-01-17|1895|1'), 
(u'1', u'|Air Conditioners|2018-01-28|19000|3'), 
(u'1', u'|Television|2018-01-11|45000|2'), 
(u'1', u'|Bottle|2018-03-24|45|10'), 
(u'1', u'|Cooking oil|2018-04-22|100|3')], 

[(u'2', u'|Gas|2018-01-17|1895|1'), 
(u'2', u'|Air Conditioners|2017-01-28|19000|3'), 
(u'2', u'|Gas|2016-01-17|2300|1')], 

[(u'3', u'|Inverter|2015-11-02|29000|1'), 
(u'3', u'|Gas|2014-01-09|2300|1'), 
(u'3', u'|Television|2018-01-17|45000|2')], 

[(u'4', u'|Gas|2018-01-17|2300|1'), 
(u'4', u'|Television$$|2018-01-17|45000|2')]
]
在下面,您可以验证每个分区中的记录数

from pyspark.sql.functions import desc
from pyspark.sql.functions import spark_partition_id

partitionSizes = newpairRDD.glom().map(len).collect();

[4, 5, 3, 3, 2]
请注意,当您创建一对RDD的键值对时,您的键应该是int类型,否则您将得到一个错误


希望这有帮助

嘿,维克兰特!
partitionBy()
repartition()
之间有什么区别?你不能互换使用它们吗?在
newpairdd=pairdd.partitionBy(5,lambda k:int(k[0])中使用
partitionBy()
而不是
repartition()
,您可能没有在此处使用
repartition()
?你能详细谈谈这两者的区别吗?@cph_sto。。是的,你可以。您可以在下面提到的链接中获得更多信息维克兰特,在过去的几个月里,我已经阅读了你的许多问题/答案,它们非常有帮助。尽管为时已晚,但请允许我把它们调高。这很好地解决了我脑海中最初的问题。非常感谢您将这些链接推荐给我。@cph\u sto。。非常感谢。