具有缓存和操作的奇怪Spark行为

时间:2017-11-22 01:38:17

标签: apache-spark caching apache-spark-sql spark-dataframe apache-spark-2.0

我一直有兴趣找出为什么我在运行某个火花工作时会遇到奇怪的行为。如果我在缓存DataFrame之后或者在将数据帧写回hdfs之前放置一个动作(A .show(1)方法),则作业将会出错。

这里有一个非常类似的帖子:

Spark SQL SaveMode.Overwrite, getting java.io.FileNotFoundException and requiring 'REFRESH TABLE tableName'

基本上,另一篇文章解释说,当你从同一个写入的HDFS目录中读取时,SaveMode"overwrite",那么你将获得java.io.FileNotFoundException

但是在这里我发现只要移动程序中的动作就可以产生非常不同的结果 - 要么完成程序要么给出这个例外。

我想知道是否有人能解释为什么Spark在这里不一致?

 val myDF = spark.read.format("csv")
    .option("header", "false")
    .option("delimiter", "\t")
    .schema(schema)
    .load(myPath)

// If I cache it here or persist it then do an action after the cache, it will occasionally 
// not throw the error. This is when completely restarting the SparkSession so there is no
// risk of another user interfering on the same JVM.

      myDF.cache()
      myDF.show(1)

// Just an example.
// Many different transformations are then applied...

val secondDF = mergeOtherDFsWithmyDF(myDF, otherDF, thirdDF)

val fourthDF = mergeTwoDFs(thirdDF, StringToCheck, fifthDF)

// Below is the same .show(1) action call as was previously done, only this below
// action ALWAYS results in a successful completion and the above .show(1) sometimes results
// in FileNotFoundException and sometimes results in successful completion. The only
// thing that changes among test runs is only one is executed. Either
// fourthDF.show(1) or myDF.show(1) is left commented out

fourthDF.show(1)
fourthDF.write
    .mode(writeMode)
    .option("header", "false")
    .option("delimiter", "\t")
    .csv(myPath)

2 个答案:

答案 0 :(得分:2)

尝试使用count代替show(1),我认为问题是由于Spark试图变得聪明并且没有加载整个数据帧(因为show并不需要所有内容)。运行count会强制Spark加载并正确缓存所有可能导致不一致的数据。

答案 1 :(得分:0)

Spark仅根据需要实现rdds,大多数操作需要读取DF的所有分区,例如count count(),但take()和first()等操作不需要所有分区。

在您的情况下,它需要一个分区,因此只实现了1个分区并进行了缓存。然后当你执行count()时,所有分区都需要实现并缓存到可用内存允许的范围内。