强制Spark DataFrame实现是否会作为检查点工作?

时间:2017-11-20 13:21:00

标签: apache-spark pyspark apache-spark-sql spark-dataframe

我在Spark 2.1.0(pySpark)中有一个带有嵌套结构的大而复杂的DataFrame,我想为它添加一个ID列。我这样做的方法是添加一个这样的列:

df= df.selectExpr('*','row_number() OVER (PARTITION BY File ORDER BY NULL) AS ID')

所以它就是例如从这个:

File     A        B
a.txt    valA1    [valB11,valB12]
a.txt    valA2    [valB21,valB22]

到此:

File     A        B                  ID
a.txt    valA1    [valB11,valB12]    1
a.txt    valA2    [valB21,valB22]    2

添加此列后,我不会立即触发Spark中的实现,但我首先将DataFrame分支到一个新变量:

dfOutput = df.select('A','ID')

只有A列和ID列,我将dfOutput写入Hive,所以我得到了的表1

A        ID
valA1    1
valA2    2

到目前为止一切顺利。然后我继续使用df进行进一步的转换,即我在列中展开一些嵌套数组并删除原始数据,如下所示:

df = df.withColumn('Bexpl',explode('B')).drop('B')

我得到了这个:

File     A        Bexpl      ID
a.txt    valA1    valB11     1
a.txt    valA1    valB12     1
a.txt    valA2    valB21     2
a.txt    valA2    valB22     2

并从中输出其他表,有时在创建第二个ID列之后,因为爆炸数组中有更多行。例如。我创建了 Table2

df= df.selectExpr('*','row_number() OVER (PARTITION BY File ORDER BY NULL) AS ID2')

得到:

File     A        Bexpl      ID    ID2
a.txt    valA1    valB11     1     1
a.txt    valA1    valB12     1     2
a.txt    valA2    valB21     2     3
a.txt    valA2    valB22     2     4

并输出如前所述:

dfOutput2 = df.select('Bexpl','ID','ID2')

得到:

Bexpl      ID    ID2
valB11     1     1
valB12     1     2
valB21     2     3
valB22     2     4

我希望第一个ID列的值保持不变,并且与创建此列的每一行的数据相匹配。这样我就可以保持dfOutput创建的 Table1 df后续表格之间的关系,如dfOutput2,结果 Table2

问题是ID和ID2不像上面的例子那样,但是混淆了,我试图找出原因。我的猜测是第一个ID列的值不是确定性的,因为df在分支到dfOutput之前没有实现。因此,当从dfOutput保存表时实际实现数据时,行会被洗牌,ID与df中稍后点上的数据不同,如dfOutput2中所示。 。但我不确定,所以我的问题是:

  1. 我的假设是否正确,虽然我在分支之前添加了ID列,但不同分支的ID生成方式不同?
  2. 在分支到dfOutput之前实现DataFrame,例如通过df.cache().count(),确保一个固定的ID列,我可以稍后从df分支,以便我可以将其用作检查点?
  3. 如果没有,我该如何解决?
  4. 我会感谢任何帮助或至少快速确认,因为我无法正确测试。 Spark只有在没有足够的内存时才会对数据进行洗牌,达到这一点意味着需要加载大量数据,反过来需要很长时间,并且仍然可以提供巧合的好结果(已经尝试过使用较小的数据集)。 / p>

1 个答案:

答案 0 :(得分:0)

我没有完全理解这个问题,但地址有些重点:

  • 窗口定义为:

    (PARTITION BY ... ORDER BY NULL) 
    

    窗口中的值的顺序实际上是随机的。它没有理由保持稳定。

  •   只有在没有足够的内存时,Spark才会对数据进行洗牌,

    每次执行计划(分组,窗口函数)需要时,Spark都会随机播放。您将此与磁盘溢出混淆,后者不会导致随机性。

  •   

    在分支到dfOutput之前实现DataFrame,例如通过df.cache()。count()

    没有。您不能依赖缓存的正确性。