Window.partitionBy之后,Spark无法重新分区

时间:2019-09-28 12:37:46

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

我有一个数据框df,其中包括两列:

  • GROUP_ID-只有3个:1、2、3
  • ELEMENT_ID-其中大约有2亿个

每个组都有多个元素。

还有其他列,例如SCORE。

我需要:

  1. 通过GROUP中的SCORE对元素进行排序,并计算每个元素的累积总和。
  2. 使用get_bucket_udf UDF将存储桶分配给GROUP中的每个SCORE。

  3. 为每个元素创建结构{'GROUP_ID', 'BUCKET', 'SCORE'}(SCORE_SET),并将这些结构聚合到每个元素的列表中。

在步骤1之前,我先按GROUP_ID进行分区,因此,步骤1-2仅在3个执行程序上运行,因为我们只有3个GROUP。

在第2步之后,我尝试通过ELEMENT_ID重新分区以利用100个执行器,但是通过查看Hadoop Resource Manager,我发现它仍然仅​​使用3个执行器。

是否可以利用所有执行者进行步骤3? 代码如下。谢谢!

#Step 1
group_id_partition = Window.partitionBy('GROUP_ID')
group_id_ordered_by_score = df_partition.orderBy('SCORE')

group_id_score_ranked = df.select(
    '*',
    func.row_number().over(group_id_ordered_by_score).alias('SCORE_RANK'))

group_id_ordered_by_rank = group_id_partition.orderBy('SCORE_RANK')

# Compute cumulative sum for each row within group_id
df_enhanced = group_id_score_ranked.select(
        'ELEMENT_ID',
        func.sum('SCORE').over(group_id_partition).alias('SCORE_SUM'),
        func.sum('SCORE').over(
            group_id_ordered_by_rank.rangeBetween(Window.unboundedPreceding, Window.currentRow)
        ).alias('SCORE_CUMSUM')
    ).orderBy('ID', 'SCORE')

# Step 2
df_enhanced_bucketed = df_enhanced.select(
    '*',
    get_bucket_udf('SCORE_SUM', 'SCORE_CUMSUM').alias('BUCKET'))

# Repartition by ELEMENT_ID - does not redistribute over all executors
df_enhanced_bucketed_repartitioned = df_enhanced_bucketed.repartition('ELEMENT_ID')

# Step 3
output_df_structed = df_enhanced_bucketed_repartitioned.select(
    'ELEMENT_ID',
    func.struct('GROUP_ID', 'BUCKET', 'SCORE').alias('SCORE_SET'))

output_df = output_df_structed.groupBy('ELEMENT_ID').agg(
    func.collect_list('SCORE_SET').alias('SCORE_SETS'))

result =  output_df.select('ELEMENT_ID', 'SCORE_SETS')
result.take(1)

0 个答案:

没有答案