[英]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.