如果我不断在其中添加列,我应该坚持Spark数据帧吗?

时间:2018-05-20 00:03:32

标签: scala apache-spark dataframe apache-spark-sql persist

我在互联网上搜索过的任何论坛都找不到关于以下主题的讨论。这可能是因为我是Spark和Scala的新手,我不是在问一个有效的问题。如果有任何现有的线程讨论相同或类似的主题,链接将非常有用。 :)

我正在开发一个使用Spark和Scala的过程,并通过读取大量表来创建文件,并通过将逻辑应用于从表中获取的数据来获取大量字段。所以,我的代码结构是这样的:

val driver_sql = "SELECT ...";

var df_res = spark.sql(driver_sql)

var df_res = df_res.withColumn("Col1", <logic>)

var df_res = df_res.withColumn("Col2", <logic>)

var df_res = df_res.withColumn("Col3", <logic>)
.
.
.

var df_res = df_res.withColumn("Col20", <logic>)

基本上,有一个驱动程序查询可以创建“驱动程序”数据帧。之后,基于驱动程序数据帧中的一个或多个键执行单独的逻辑(函数)以添加新的列/字段。 “逻辑”部分并不总是单行代码,有时,它是一个单独的函数,它运行另一个查询并在df_res上进行某种连接并添加一个新列。 记录计数也会发生变化,因为在某些情况下我使用“内部”连接与其他表/数据帧。

所以,这是我的问题:

  • 我应该在任何时间点坚持df_res吗?
  • 添加列后,我可以一次又一次地坚持df_res吗?我的意思是,它增加了价值吗?
  • 如果每次添加新列时我都坚持df_res(仅限磁盘),是否更换了磁盘中的数据?或者它是否在磁盘中创建df_res的新副本/版本?
  • 是否有更好的技术可以在这样的场景中持久保存/缓存数据(以避免在内存中做很多事情)?

1 个答案:

答案 0 :(得分:0)

当您要在数据帧上应用迭代操作时,第一件事就是持久保存数据帧。
您在这里所做的就是在数据帧上应用转换操作。无需在此处保留这些数据框。
例如:-如果您正在做这样的事情,坚持下去会有所帮助。

val df = spark.sql("select * from ...").persist

df.count

val df1 = df.select("..").withColumn("xyz",udf(..))

df1.count

val df2 = df.select("..").withColumn("abc",udf2(..))

df2.count

现在,如果您在此处坚持df,那么在计算df1和df2时将是有益的。 这里还要注意的另一件事是,我执行df.count的原因是因为只有在对其执行操作时,数据帧才会保留。从Spark文档: “第一次在操作中对其进行计算,它将保存在节点上的内存中”。这也回答了您的第二个问题。

每次您持久保存都会创建一个新副本,但是您应该首先取消保留上一个。