我有2个Spark数据帧(A和B),两者都具有相同的列/字段(这是DataFrame A中的主键,而在B中不是主键)。
对于数据框A中的每个记录/行,数据框B中有多个记录。 基于该公共列值,我想针对数据帧A中的每个记录从数据帧B中获取所有记录。
我应该执行哪种转换才能将记录收集在一起而无需进行太多改组?
答案 0 :(得分:2)
要合并2个或更多spark数据帧中的记录,必须进行连接。
如果您的数据没有很好地分区/存储,将导致随机连接。每个节点与每个其他节点进行对话,并根据哪个节点具有某个键或一组键(要加入的键)共享数据。这些连接很昂贵,因为网络可能会变得拥塞。
在以下情况下可以避免随机播放:
分区
如果在联接之前正确地对数据进行了分区,则可以提高执行效率,因为即使计划了改组,如果来自两个不同DataFrame的数据已经位于同一台计算机上,Spark也可以避免改组
df1.repartition(col("id"))
df2.repartition(col("id"))
// you can optionally specify the number of partitions like:
df1.repartition(10, col("id"))
// Join Dataframes on id column
df1.join(df2, "id") // this will avoid the duplicate id columns in output DF.
广播哈希加入
当数据集之一足够小以适合单个工作节点的内存时,我们可以优化联接。
Spark会将小型DataFrame复制到群集中的每个工作程序节点(位于一台或多台计算机上)。现在,这听起来很昂贵。但是,这样做会阻止我们在整个加入过程中执行所有所有人的通信。相反,它在开始时只执行一次,然后让每个单独的工作程序节点执行工作,而不必等待任何其他工作程序节点或与之通信。
import org.apache.spark.sql.functions.broadcast
// explicitly specify the broadcast hint, though spark handles it.
df1.join(broadcast(df2), "id")