Apache spark 性能:按先前分组列的子集分组

Apache spark 性能:按先前分组列的子集分组,apache-spark,dataframe,apache-spark-sql,Apache Spark,Dataframe,Apache Spark Sql,我有一个带有两个分类列的数据框架,类似于以下示例: +----+-------+-------+ | ID | Cat A | Cat B | +----+-------+-------+ | 1 | A | B | | 2 | B | C | | 5 | A | B | | 7 | B | C | | 8 | A | C | +----+-------+-------+ 我需要做一些处理,这需要两个步骤

我有一个带有两个分类列的数据框架,类似于以下示例:

+----+-------+-------+
| ID | Cat A | Cat B |
+----+-------+-------+
|  1 |   A   |   B   |
|  2 |   B   |   C   |
|  5 |   A   |   B   |
|  7 |   B   |   C   |
|  8 |   A   |   C   |
+----+-------+-------+
我需要做一些处理,这需要两个步骤:第一个步骤需要将数据按两个分类列分组。在本例中,它将生成以下数据帧:

+-------+-------+-----+
| Cat A | Cat B | Cnt |
+-------+-------+-----+
|   A   |   B   |  2  |
|   B   |   C   |  2  |
|   A   |   C   |  1  |
+-------+-------+-----+
然后,下一步包括仅按CatA分组,以计算新的聚合,例如:

+-----+-----+
| Cat | Cnt |
+-----+-----+
|  A  |  3  |
|  B  |  2  |
+-----+-----+
现在是问题:

  • 在我的解决方案中,我通过

    val df2=df.groupBy(“catA”、“catB”).agg(…)
    
    然后我将这个
    df2
    进行聚合,得到最后一个:

    val df3=df2.groupBy(“catA”).agg(…)
    
    我认为它比再次聚合第一个DF更有效。这是一个好的假设吗?还是没什么区别

  • 有没有更有效的方法来达到同样的效果的建议


  • 一般来说,它看起来是一种很好的方法,应该比两次聚合数据更有效。由于洗牌文件是隐式缓存的,所以至少部分工作应该只执行一次。因此,当您在
    df2
    上调用操作,然后在
    df3
    上调用操作时,您应该会看到与
    df2
    对应的阶段已被跳过。此外,在第二次
    agg
    期间,由第一次洗牌强制执行的部分结构可能会减少聚合缓冲区的内存需求


    不幸的是,
    DataFrame
    聚合与RDD聚合不同,不能使用自定义分区器。这意味着您不能基于
    catA
    的值使用一次洗牌来计算两个数据帧。这意味着第二次聚合将需要单独的exchange哈希分区。我怀疑切换到
    RDD是否合理一般来说,这看起来是一个好方法,应该比两次聚合数据更有效。由于洗牌文件是隐式缓存的,所以至少部分工作应该只执行一次。因此,当您在
    df2
    上调用操作,然后在
    df3
    上调用操作时,您应该会看到与
    df2
    对应的阶段已被跳过。此外,在第二次
    agg
    期间,由第一次洗牌强制执行的部分结构可能会减少聚合缓冲区的内存需求

    不幸的是,
    DataFrame
    聚合与RDD聚合不同,不能使用自定义分区器。这意味着您不能基于
    catA
    的值使用一次洗牌来计算两个数据帧。这意味着第二次聚合将需要单独的exchange哈希分区。我怀疑它是否有理由切换到
    RDDs