如果多次使用,是否需要缓存RDD?

Met*_*est 3 python hadoop scala apache-spark rdd

比方说,我们有以下代码.

x = sc.textFile(...)
y = x.map(...)
z = x.map(...)
Run Code Online (Sandbox Code Playgroud)

缓存x在这里是否必不可少?不会缓存x使spark读取输入文件两次?

Aja*_*pta 7

这些东西没有必要让Spark读取输入两次.

列出所有可能的场景:

示例1:文件甚至没有读过一次

x = sc.textFile(...)    #creation of RDD
y = x.map(...)    #Transformation of RDD
z = x.map(...)    #Transformation of RDD
Run Code Online (Sandbox Code Playgroud)

在这种情况下,它不会做任何事情,因为转换没有动作.

示例2:文件读取一次

x = sc.textFile(...)    #creation of RDD
y = x.map(...)    #Transformation of RDD
z = x.map(...)    #Transformation of RDD
println(y.count())    #Action of RDD
Run Code Online (Sandbox Code Playgroud)

只有一次为y读取文件才能使其映射

示例3:文件读取两次

x = sc.textFile(...)    #creation of RDD
y = x.map(...)    #Transformation of RDD
z = x.map(...)    #Transformation of RDD
println(y.count())    #Action of RDD
println(z.count())    #Action of RDD
Run Code Online (Sandbox Code Playgroud)

它现在只会读取输入文件两次,因为操作与转换一起使用.

示例4:文件读取一次

x = sc.textFile(...)    #creation of RDD
y = x.map(...)    #Transformation of RDD
z = y.map(...)    #Transformation of RDD
println(z.count())    #Action of RDD
Run Code Online (Sandbox Code Playgroud)

示例5:文件读取两次

x = sc.textFile(...)    #creation of RDD
y = x.map(...)    #Transformation of RDD
z = y.map(...)    #Transformation of RDD
println(y.count())    #Action of RDD
println(z.count())    #Action of RDD
Run Code Online (Sandbox Code Playgroud)

由于动作现在用于两个不同的RDD,因此它将读取两次.

示例6:文件读取一次

x = sc.textFile(...)    #creation of RDD
y = x.map(...).cache()    #Transformation of RDD
z = y.map(...)    #Transformation of RDD
println(y.count())    #Action of RDD
println(z.count())    #Action of RDD
Run Code Online (Sandbox Code Playgroud)

即使现在,只有在执行RDD并将其存储到存储器中时才使用两个不同的动作.现在第二个操作发生在缓存的RDD上.

编辑:附加信息

所以问题出现了什么缓存和什么不缓存?
Ans:您将一次又一次使用的RDD需要缓存.
例7:

x = sc.textFile(...)    #creation of RDD
y = x.map(...)    #Transformation of RDD
z = x.map(...)    #Transformation of RDD
Run Code Online (Sandbox Code Playgroud)

所以在这种情况下,我们x一次又一次地使用x.所以建议缓存.因为它不必x一次又一次地从源读取.所以如果你正在处理大量数据,这将节省大量的时间您.

假设您开始使用/不使用序列化将所有RDD作为内存/磁盘中的缓存.如果执行任何任务,如果Spark有更少的内存,那么它将开始使用LRU(最近最近使用)策略删除旧的RDD.每当再次使用移除的RDD时,它将执行从源到达的所有步骤,直到RDD转换.

  • 很棒的答案!很好的例子.`first`只会触发第一个分区的处理.(除非它是空的.)你可以提到这个或使用`count`代替一个动作.我要补充的另一件事是,重新读取文件可能比缓存它更快.决定是否一般缓存的唯一方法是对特定代码进行基准测试.(根据经验,我同意你的建议!) (2认同)