Scala Spark-作用域、数据帧和内存管理

Scala Spark-作用域、数据帧和内存管理,scala,apache-spark,spark-dataframe,Scala,Apache Spark,Spark Dataframe,我很好奇scope如何与Data Frame和Spark一起工作。在下面的示例中,我有一个文件列表,每个文件独立加载到一个数据帧中,执行一些操作,然后将dfOutput写入磁盘 val files = getListOfFiles("outputs/emailsSplit") for (file <- files){ val df = sqlContext.read .format("com.databricks.spark.csv") .option("

我很好奇scope如何与Data Frame和Spark一起工作。在下面的示例中,我有一个文件列表,每个文件独立加载到一个数据帧中,执行一些操作,然后将
dfOutput
写入磁盘

val files = getListOfFiles("outputs/emailsSplit")

for (file <- files){

   val df = sqlContext.read
      .format("com.databricks.spark.csv")
      .option("delimiter","\t")          // Delimiter is tab
      .option("parserLib", "UNIVOCITY")  // Parser, which deals better with the email formatting
      .schema(customSchema)              // Schema of the table
      .load(file.toString)                        // Input file


   val dfOutput = df.[stuff happens]

    dfOutput.write.format("com.databricks.spark.csv").mode("overwrite").option("header", "true").save("outputs/sentSplit/sentiment"+file.toString+".csv") 

}
val files=getListOfFiles(“输出/emailsSplit”)

对于(file
DataFrame
对象很小。但是,它们可以引用Spark executors上缓存中的数据,也可以引用Spark executors上的随机文件。当
数据帧
被垃圾收集时,也会导致删除执行器上的缓存和随机文件

在您的代码中,没有对经过循环的数据帧的引用。因此它们是符合条件的垃圾收集。垃圾收集通常是根据内存压力进行的。如果您担心洗牌文件会填满磁盘,则触发显式GC以确保删除不再存在的数据帧的洗牌文件可能是有意义的参考资料

根据您对数据帧所做的操作(
[stuff Accounts]
),可能没有数据存储在内存中。这是Spark中的默认操作模式。如果您只想读取一些数据,对其进行转换,然后将其写回,则所有数据都会逐行发生,而不会将任何数据存储在内存中。(缓存仅在您明确请求时发生。)


有了这些,我建议在出现问题之前不要担心内存管理。

DataFrame
对象很小。但是它们可以在Spark executors上引用缓存中的数据,也可以在Spark executors上引用随机文件。当
数据帧
被垃圾收集时,也会导致缓存和随机文件丢失要删除执行人上的les

在您的代码中,没有对经过循环的数据帧的引用。因此它们是符合条件的垃圾收集。垃圾收集通常是根据内存压力进行的。如果您担心洗牌文件会填满磁盘,则触发显式GC以确保删除不再存在的数据帧的洗牌文件可能是有意义的参考资料

根据您对数据帧所做的操作(
[stuff Accounts]
),可能没有数据存储在内存中。这是Spark中的默认操作模式。如果您只想读取一些数据,对其进行转换,然后将其写回,则所有数据都会逐行发生,而不会将任何数据存储在内存中。(缓存仅在您明确请求时发生。)


有了这些,我建议在出现问题之前不要担心内存管理。

谢谢,非常有启发性的回答!给定df上的线性转换过程,可以说类似于df1=df0.bla();df2=df1.blabla();df3=df2.blabla(),当df1被丢弃时?在它所处的作用域的末尾,或者当程序意识到它将不再继续使用时(基本上是在创建df2之后,因为没有进一步调用df1)?子代RDD(如
df2
中的RDD)引用它们的父代(如
df1
中的RDD)因此,只有当
df1
超出作用域并且其所有子体都已被垃圾收集时,才会收集它。这是因为RDD是惰性的。只有在执行操作(例如“计数行”)时,
df1
中的指令(例如“读取此文件”)才会立即执行因此必须保留对祖先RDD的引用。谢谢,非常有启发性的回答!给定df上的线性转换过程,比如df1=df0.bla();df2=df1.blabla();df3=df2.blabla(),当df1被丢弃时?在它所处的作用域的末尾,或者当程序意识到它将不再继续使用时(基本上是在创建df2之后,因为没有进一步调用df1)?子代RDD(如
df2
中的RDD)引用它们的父代(如
df1
中的RDD)因此,只有当
df1
超出作用域并且其所有子体都已被垃圾收集时,才会收集它。这是因为RDD是惰性的。只有在执行操作(例如“计数行”)时,
df1
中的指令(例如“读取此文件”)才会立即执行因此必须保留对祖先RDD的引用。