Apache Spark中缓存供其他DataFrame调用的无动作DataFrame相关问题
Apache Spark DataFrame 相关问题解答
1. 在Apache Spark中,存储自身不执行动作但会被其他执行动作的DataFrame调用的DataFrame是否有意义?
当然有意义。Spark里的DataFrame本质是惰性求值的执行计划,本身不会触发计算,只有遇到count()、show()这类动作算子才会真正执行计算。如果一个DataFrame会被多个其他DataFrame复用(比如示例中的dataFrameA被dataFrameB和dataFrameC交叉连接),提前定义好这个DataFrame可以:
- 避免重复编写相同的读取、过滤等逻辑,让代码更简洁、易维护
- 方便后续对这个复用逻辑统一做优化(比如缓存、调整分区)
- 让执行计划结构更清晰,便于排查问题
2. 若缓存一个自身不执行动作、但会被其他执行动作的DataFrame调用的DataFrame,会发生什么?示例中的DataFrameA会被缓存吗?
首先要明确:cache()是一个转换算子,调用它只会给DataFrame的执行计划打上缓存标记,不会立刻触发缓存操作。当依赖这个DataFrame的动作算子第一次执行时,Spark会先计算该DataFrame的结果,然后将结果缓存到内存(默认缓存级别,也可通过persist()指定其他级别)。后续再遇到依赖该DataFrame的动作时,就直接复用缓存中的数据,无需重新执行之前的读取、过滤等逻辑,能显著提升重复计算的性能。
针对示例代码:DataFrameA会被缓存。第一次执行resultB.count()时,Spark会执行dataFrameA对应的读取、过滤逻辑,计算出结果后完成缓存;之后执行resutC.count()时,会直接使用缓存中的dataFrameA数据,不用重新读取pathA的CSV文件并过滤。
示例代码
val sparkS: SparkSession = SparkSession.builder().getOrCreate() val dataFrameA : DataFrame = sparkS.read .option("header", "true") .option("inferSchema", "true") .csv(pathA) .filter( condition ).cache() val dataFrameB : DataFrame = sparkS.read .option("header", "true") .option("inferSchema", "true") .csv(pathB) val dataFrameC : DataFrame = sparkS.read .option("header", "true") .option("inferSchema", "true") .csv(pathC) val resultB = dataFrameB.crossJoin(dataFrameA) resultB.count() resultB.show() val resutC = dataFrameC.crossJoin(dataFrameA) resutC.count() resutC.show()
内容的提问来源于stack exchange,提问作者Felipe Tapia
相关产品推荐
相关产品推荐

