如何仅在Spark中缓存部分RDD?

时间:2018-07-12 20:02:49

标签: java scala apache-spark caching

我有一个PairRDD<Metadata, BigData>

我想执行两项操作:一项针对RDD中的所有数据,另一项仅针对元数据。

输入来自读取海量文件,我不想重复。

我知道经典的做法是在输入RDD上使用cache()persist()以便将其保存在内存中:

JavaPairRDD<Metadata, Bigdata> inputRDD = expensiveSource();
JavaPairRDD<Metadata, Bigdata> cachedRDD = inputRDD.cache();
cachedRDD.foreach(doWorkOnAllData);
cachedRDD.keys().foreach(doWorkOnMetadata);

问题在于输入量太大,以致无法容纳在内存中,因此cache()不能执行任何操作。

我可以使用persist()将其缓存在磁盘上,但是由于数据很大,因此保存和读取所有数据实际上比读取原始数据要慢。

我可以使用MEMORY_SERDE来获得一些空间,但这可能是不够的,即使当我只对0.1%的数据感兴趣时,甚至整个序列化都显得很愚蠢。

我想要的是仅缓存我的PairRDD的关键部分。我以为可以通过在cache() keys()上调用RDD来做到这一点:

JavaPairRDD<Metadata, Bigdata> inputRDD = expensiveSource();
JavaRDD<Metadata, Bigdata> cachedRDD = inputRDD.keys().cache();
inputRDD.foreach(doWorkOnAllData);
cachedRDD.foreach(doWorkOnMetadata);

但是在那种情况下,它似乎并没有缓存任何东西,而只是返回以加载源代码。

是否可以仅将一部分数据放入缓存?对元数据的操作非常小,但是在对整个数据进行操作之后,我必须这样做。

1 个答案:

答案 0 :(得分:0)

只有调用inputRDD.keys()

,Spark才会从缓存中加载RDD

您可以尝试的是:JavaRDD<Metadata> keys = inputRDD.keys().cache();来缓存JavaRDD<Metadata>

然后创建缓存的RDD:

JavaRDD<Metadata,Bigdata> cachedRDD = keys.join(JavaPairRDD<Bigdata>)

如果您的RDD很大,则第一次从缓存中读取速度最慢,因为您必须保存RDD,但是下次读取它时,它将更快。