[英]How to partition RDD by key in Spark?
鑒於HashPartitioner文檔說:
[HashPartitioner]使用Java的Object.hashCode實現基於哈希的分區。
假設我DeviceData
kind
對DeviceData
進行分區。
case class DeviceData(kind: String, time: Long, data: String)
通過覆蓋deviceData.hashCode()
方法並僅使用kind
的哈希碼對RDD[DeviceData]
進行分區是否正確?
但是考慮到HashPartitioner
帶有多個partitions參數,我對於是否需要提前知道種類數以及如果種類多於分區會發生什么感到困惑?
如果我將分區數據寫到磁盤上,它將在讀取時保持分區狀態是否正確?
我的目標是打電話
deviceDataRdd.foreachPartition(d: Iterator[DeviceData] => ...)
並且在迭代器中僅具有相同kind
值的DeviceData
。
僅使用kind
做一個groupByKey
kind
? 或另一個PairRDDFunctions
方法。
在我看來,您似乎並不真正在乎分區,只是在一個處理流程中獲得了所有特定種類的分區?
對函數允許這樣做:
rdd.keyBy(_.kind).partitionBy(new HashPartitioner(PARTITIONS))
.foreachPartition(...)
但是,您可能會更安全一些:
rdd.keyBy(_.kind).reduceByKey(....)
或mapValues
或許多其他對函數,這些函數可以確保您整體上獲得所需的知識
通過覆蓋deviceData.hashCode()方法並僅使用類型的哈希碼來對RDD [DeviceData]進行分區是否正確?
不會的。 如果您查看Java Object.hashCode
文檔,則會發現有關hashCode
常規約定的以下信息:
如果根據equals(Object)方法,兩個對象相等,則在兩個對象中的每個對象上調用hashCode方法必須產生相同的整數結果。
因此,除非完全基於kind
設備的平等概念適合您的用例,並且我對此表示嚴重懷疑,否則對HashCode
進行修改以獲取所需的分區是一個壞主意。 通常,您應該實現自己的分區程序,但這不是必需的。
由於不包括SQL和GraphX中的特殊方案,所以partitionBy
僅在PairRDD
上有效,因此創建RDD[(String, DeviceData)]
並使用普通的HashPartitioner
是有意義的
deviceDataRdd.map(dev => (dev.kind, dev)).partitionBy(new HashPartitioner(n))
只要記住,在所處的環境kind
具有低基數或將其用於分區可能不是最佳解決方案高度偏態分布。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.