加入庞大而庞大的火花数据帧

时间:2018-04-20 02:51:59

标签: python apache-spark dataframe pyspark bigdata

我的问题如下:

  • 我有一个名为details的大型数据框,其中包含900K行,另一个包含名为attributes的80M行。

  • 两者都有一列A,我希望在其中进行左外连接,左侧数据框为deatils

  • 数据框A中的列details中只有75K个唯一条目。列attributes中的数据框A 80M唯一条目。

实现join操作的最佳方式是什么?

我尝试了什么?

  • 简单连接,即details.join(attributes, "A", how="left_outer")只是超时(或内存不足)。

  • 由于A中的details列中只有75K个唯一条目,因此我们并不关心attributes中数据框中的其余内容。所以,首先我使用以下方法过滤:

    uniqueA = details.select('A').distinct().collect()
    uniqueA = map(lambda x: x.A, uniqueA)
    attributes_filtered = attributes.filter(attributes.A.isin(*uniqueA))
    

    我认为这会有效,因为attributes表从80M行下降到仅75K行。但是,完成join(它永远不会完成)仍然需要永远。

  • 接下来,我认为分区太多,要连接的数据不在同一个分区上。虽然,我不知道如何将所有数据带到同一个分区,但我认为重新分区可能有所帮助。所以就这样了。

    details_repartitioned = details.repartition("A")
    attributes_repartitioned = attributes.repartition("A")
    
  • 上述操作将attributes中的分区数从70K减少到200. details中的分区数约为1100.

    details_attributes = details_repartitioned.join(broadcast(
    attributes_repartitioned), "A", how='left_outer')  # tried without broadcast too
    

毕竟,join仍然不起作用。我还在学习PySpark,所以我可能误解了重新分区背后的基本原理。如果有人能够阐明这一点,那就太棒了。

P.S。我已经看过this个问题,但是这个问题没有回答。

1 个答案:

答案 0 :(得分:3)

详细信息表有900k项,A列有75k个不同的条目。我认为您尝试过的A列上的过滤器是正确的方向。然而,收集并遵循地图操作

attributes_filtered = attributes.filter(attributes.A.isin(*uniqueA)) 
这太贵了。另一种方法是

uniqueA = details.select('A').distinct().persist(StorageLevel.DISK_ONLY)
uniqueA.count // Breaking the DAG lineage
attrJoined = attributes.join(uniqueA, "inner")

另外,如果你还没有这样做,你可能需要正确设置shuffle分区。

您的数据集中可能发生的一个问题是偏差。它可能发生在75k唯一值中,只有少数与属性表中的大量行连接。在这种情况下,加入可能需要更长的时间,可能无法完成。

要解决此问题,您需要找到A列的偏斜值并单独处理它们。