Apache spark 具有缓存和动作的奇怪Spark行为
我一直很想知道为什么我在从事某项星火工作时会有奇怪的行为。如果在缓存数据帧之后或将数据帧写回hdfs之前放置操作(AApache spark 具有缓存和动作的奇怪Spark行为,apache-spark,caching,apache-spark-sql,spark-dataframe,apache-spark-2.0,Apache Spark,Caching,Apache Spark Sql,Spark Dataframe,Apache Spark 2.0,我一直很想知道为什么我在从事某项星火工作时会有奇怪的行为。如果在缓存数据帧之后或将数据帧写回hdfs之前放置操作(A.show(1)方法),作业将出错 这里有一个非常类似于SO的帖子: 基本上,另一篇文章解释说,当您从正在写入的同一个HDFS目录中读取,并且您的SaveMode是“overwrite”,那么您将得到java.io.FileNotFoundException 但在这里,我发现仅仅是在程序中移动动作的位置就可以得到非常不同的结果——要么完成程序,要么给出这个异常 我想知道是否有人能
.show(1)
方法),作业将出错
这里有一个非常类似于SO的帖子:
基本上,另一篇文章解释说,当您从正在写入的同一个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)
尝试使用
count
而不是show(1)
,我认为问题在于Spark试图变得聪明,而不是加载整个数据帧(因为show
并不需要所有东西)。运行count
将强制Spark加载并正确缓存所有数据,这将有希望消除不一致性。尝试使用count
而不是show(1)
,我相信问题是因为Spark试图变得聪明,而不是加载整个数据帧(因为show
并不需要所有东西). 运行count
强制Spark加载并正确缓存所有数据,这将有希望消除不一致性。Spark仅根据需要实现RDD,大多数操作需要读取DF的所有分区,例如us count(),但take()和first()等操作不需要所有分区
在您的情况下,它需要一个分区,因此只有一个分区被物化和缓存。然后,当您执行count()时,需要在可用内存允许的范围内对所有分区进行物化和缓存。Spark仅按需物化RDD,大多数操作需要读取DF的所有分区,例如us count(),但take()和first()等操作不需要所有分区
在您的情况下,它需要一个分区,因此只有一个分区被物化和缓存。然后,在执行count()时,所有分区都需要具体化并缓存到可用内存允许的范围内。我来检查一下!您可以考虑使用<代码>前缀分区(x= > {})< /COD>而不是计数。可能不会有明显的区别,但计数需要聚合,而
foreachPartition
不需要聚合。这是否意味着您可以在缓存之后使用计数,以使缓存立即实际缓存中间数据?我会检查这个!您可以考虑使用<代码>前缀分区(x= > {})< /COD>而不是计数。可能不会有明显的区别,但count需要聚合,而foreachPartition
不需要聚合。这是否意味着您可以在缓存之后使用count,使缓存立即实际缓存中间数据?