簡體   English   中英

Spark RDD 以獨占方式按鍵分區

[英]Spark RDD partition by key in exclusive way

我想按鍵對 RDD 進行分區,並且每個分區只包含一個鍵的值。 例如,如果我有 100 個不同的鍵值並且我repartition(102) ,那么 RDD 應該有 2 個空分區和 100 個分區,每個分區包含一個鍵值。

我嘗試使用groupByKey(k).repartition(102)但這並不能保證每個分區中鍵的獨占性,因為我看到一些分區包含更多單個鍵的值和超過 2 個空值。

標准 API 中有沒有辦法做到這一點?

要使用 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)

讓我們看看數據在這 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 類型,否則您將收到錯誤消息。

希望這可以幫助!

對於 RDD,您是否嘗試過使用partitionBy按鍵對 RDD 進行分區,例如在這個問題中 如果需要,您可以將分區數指定為刪除空分區的鍵數。

在數據集API,你可以使用再分配Column在該列由值作為參數傳遞給分區(但是注意,這里使用的價值spark.sql.shuffle.partitions作為分區的數量,所以你會得到更多空分區)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM