我有一个很大的RDD[(K, V)]
。为了映射这些值,我需要一个每个密钥都很常见的大型数据结构,并且构建起来很昂贵。我之后无法执行groupByKey
并执行flatMap
,因为每个密钥的值都不适合内存。我无法加载所有结构,因为它们也不适合内存。如何每组执行一次结构初始化(或最少次数),然后将其删除?
使用例
答案 0 :(得分:0)
根据您的用例,您可以为这个大型数据结构使用广播变量
CREATE TRIGGER update_child_validitiy AFTER UPDATE ON parents
FOR EACH ROW
BEGIN
UPDATE children SET child_validity = NEW.parent_validity WHERE id = NEW.id;
END;
http://spark.apache.org/docs/latest/programming-guide.html#broadcast-variables
或者您可以使用val broadcastVar = sc.broadcast(LargeThingy())
broadcastVar.value
并为每个分区初始化一个大的东西,然后处理分区中的数据:
rdd.foreachPartition
答案 1 :(得分:0)
例如,您可以RDD
使用repartitionAndSortWithinPartitions
后跟mapPartitions
:
val partitioner: org.apache.spark.Partitioner = ???
rdd.repartitionAndSortWithinPartition(partitioner).mapPartitions { iter => {
var currentKey: Option[String] = None
var currentTrie: Option[Trie] = None
iter.map {
case (k, v) =>
.. // if Option(k) != currentKey update currentKey and currentTrie
.. // Proceed with logic
}
}}
或Dataset
groupBy
后跟flatMapGroups
:
rdd.toDS.groupByKey(_._1).flatMapGroups { case (key, iter) => {
val currentTrie: Trie = ???
iter.map { case (_, v) => ??? }
})
与其RDD
对应Dataset
不同,不必同时将所有值加载到内存中,因此各个组的大小不应成为问题。
两种解决方案都需要完全随机播放,但每个参考结构只会为每个键初始化一次。