HashPartitionerのドキュメントが言うことを考えると:
[HashPartitioner]は、JavaのObject.hashCodeを使用してハッシュベースのパーティショニングを実装します。
DeviceData
をそのkind
で分割したいとします。
_case class DeviceData(kind: String, time: Long, data: String)
_
deviceData.hashCode()
メソッドを上書きして_RDD[DeviceData]
_を分割し、kind
のハッシュコードのみを使用することは正しいでしょうか?
しかし、HashPartitioner
がいくつかのパーティションパラメーターを受け取ることを考えると、種類の数を事前に知る必要があるかどうかと、パーティションよりも種類が多い場合はどうなるかについて混乱しますか?
パーティション化されたデータをディスクに書き込んだ場合、読み取り時にパーティション化されたままになるのは正しいことですか?
私の目標は電話することです
_ deviceDataRdd.foreachPartition(d: Iterator[DeviceData] => ...)
_
また、イテレータには同じDeviceData
値のkind
のみを含めます。
groupByKey
を使用してkind
を実行するのはどうですか。または別のPairRDDFunctions
メソッド。
あなたはパーティション分割について本当に気にしていないように見えますが、1つの処理フローで特定の種類のすべてを取得しているだけですか?
ペア関数はこれを可能にします:
rdd.keyBy(_.kind).partitionBy(new HashPartitioner(PARTITIONS))
.foreachPartition(...)
ただし、次のようなものを使用すると、おそらく少し安全になります。
rdd.keyBy(_.kind).reduceByKey(....)
またはmapValues
または、全体としてピースを取得することを保証する他のいくつかのペア関数
DeviceData.hashCode()メソッドを上書きしてRDD [DeviceData]を分割し、種類のハッシュコードのみを使用することは正しいでしょうか?
そうではありません。 Java _Object.hashCode
_のドキュメントを参照すると、hashCode
の一般契約に関する次の情報が見つかります。
Equals(Object)メソッドに従って2つのオブジェクトが等しい場合、2つのオブジェクトのそれぞれでhashCodeメソッドを呼び出すと、同じ整数の結果が生成される必要があります。
したがって、純粋にkind
のデバイスに基づく等式の概念がユースケースに適合しない限り、私がそれを真剣に疑っていない限り、HashCode
をいじって目的のパーティション分割を取得することは悪い考えです。一般的には 独自のパーティショナーを実装する が必要ですが、ここでは必要ありません。
SQLとGraphXの特殊なシナリオを除いて、partitionBy
はPairRDD
でのみ有効であるため、RDD[(String, DeviceData)]
を作成してプレーンHashPartitioner
を使用することは理にかなっています
_deviceDataRdd.map(dev => (dev.kind, dev)).partitionBy(new HashPartitioner(n))
_
kind
のカーディナリティが低い場合や、分配にそれを使用して分布が大きく歪んでいる場合は、最適なソリューションではない可能性があることに注意してください。