Согласно книге Spark - The Definitive Guide
Spark имеет два встроенных разделителя: HashPartitioner
для дискретных значений и RangePartitioner
. Оба работают для дискретных и непрерывных значений.
Пример HashPartitioner:
import org.apache.spark.HashPartitioner
val rdd = df.rdd // convert DataFrame to low-level RDD
val keyedRDD = rdd.keyBy(...) // define your custom key
keyedRDD.partitionBy(new HashPartitioner(n))
Пример разделителя:
import org.apache.spark.Partitioner
class DomainParitioner extends Partitioner {
def numPartitions = n
def getPartition(key: Any): Int = {
// your custome partition logic
}
}
keyedRDD.partitionBy(new DomainPartitioner).map(_._1).glom().map(_.toSet.toSeq.length)
В книге также упоминается, что вам следует остерегаться key skew
, что означает, что некоторые ключи могут иметь много-много больше значений, чем другие ключи. Вы хотите максимально разбить эти ключи, чтобы улучшить параллелизм и предотвратить OutOfMemoryErrors
во время выполнения.