Apache spark 对于Spark数据帧中的右外连接,是否有更好的替代方案?以及如何有条件地转换行?

Apache spark 对于Spark数据帧中的右外连接,是否有更好的替代方案?以及如何有条件地转换行?,apache-spark,apache-spark-sql,spark-dataframe,Apache Spark,Apache Spark Sql,Spark Dataframe,我为一个很长的问题提前道歉。我会尽量用一个简单的例子来解释。我有以下两个数据帧df1和df2 +---------+-------+-------+ | CATEGORY| REGION| avgCol| +-------- +-------+-------+ | CAT-1| NORTH| 0.575| | CAT-1| SOUTH| 15.879| | CAT-2| NORTH| 5.255| +---------+-------+-------+ df1: +

我为一个很长的问题提前道歉。我会尽量用一个简单的例子来解释。我有以下两个数据帧df1df2

+---------+-------+-------+
| CATEGORY| REGION| avgCol|
+-------- +-------+-------+
|    CAT-1|  NORTH|  0.575|
|    CAT-1|  SOUTH| 15.879|
|    CAT-2|  NORTH|  5.255|
+---------+-------+-------+
df1:

+------+---------+-------+-------+-------+
|   PID| CATEGORY| REGION| VOLUME| RESULT|
+------+-------- +-------+-------+-------+
|123456|    CAT-1|  NORTH|    200|  1.345|
|123456|    CAT-1|  SOUTH|    125|  2.890|
|123456|    CAT-2|  NORTH|     75|  6.755|
|123456|    CAT-2|  SOUTH|    100|  0.432|
|123456|    CAT-3|  NORTH|     50|  5.111|
+------+---------+-------+-------+-------+
df2

+---------+-------+-------+
| CATEGORY| REGION| avgCol|
+-------- +-------+-------+
|    CAT-1|  NORTH|  0.575|
|    CAT-1|  SOUTH| 15.879|
|    CAT-2|  NORTH|  5.255|
+---------+-------+-------+
我想加入这两个DFs以获得第三个DF df3

+------+---------+-------+-------+-------+-------+
|   PID| CATEGORY| REGION| avgCol| VOLUME| RESULT|
+------+-------- +-------+-------+-------+-------+
|123456|    CAT-1|  NORTH|  0.575|    200|  1.345|
|123456|    CAT-1|  SOUTH| 15.879|    125|  2.890|
|123456|    CAT-2|  NORTH|  5.255|     75|  6.755|
|123456|    CAT-2|  SOUTH|   null|    100|  0.432|
|123456|    CAT-3|  NORTH|   null|     50|  5.111|
+------+---------+-------+-------+-------+-------+
我用了正确的外部连接。代码看起来像

DataFrame df3 = df1.join(df2, joinCols, "right_outer");
df3.withColumn("NEW_RESULT", when(col("avgCol").isNotNull(), getResult(avgCol).otherwise(col("RESULT"))
    .drop("RESULT").withColumnRenamed("NEW_RESULT", "RESULT)
+------+---------+-------+-------+-------+-------+
|   PID| CATEGORY| REGION| avgCol| VOLUME| RESULT|
+------+-------- +-------+-------+-------+-------+
|123456|    CAT-1|  NORTH|  0.575|    200|  8.543|
|123456|    CAT-1|  SOUTH| 15.879|    125|  4.321|
|123456|    CAT-2|  NORTH|  5.255|     75|  7.012|
|123456|    CAT-2|  SOUTH|   null|    100|  0.432|
|123456|    CAT-3|  NORTH|   null|     50|  5.111|
+------+---------+-------+-------+-------+-------+
其中,joinCols是我要加入的列的集合

然后,我想将df3转换为一个数据帧,其中RESULT的值仅针对avgCol为空的行新计算。实现这一点的代码如下所示

DataFrame df3 = df1.join(df2, joinCols, "right_outer");
df3.withColumn("NEW_RESULT", when(col("avgCol").isNotNull(), getResult(avgCol).otherwise(col("RESULT"))
    .drop("RESULT").withColumnRenamed("NEW_RESULT", "RESULT)
+------+---------+-------+-------+-------+-------+
|   PID| CATEGORY| REGION| avgCol| VOLUME| RESULT|
+------+-------- +-------+-------+-------+-------+
|123456|    CAT-1|  NORTH|  0.575|    200|  8.543|
|123456|    CAT-1|  SOUTH| 15.879|    125|  4.321|
|123456|    CAT-2|  NORTH|  5.255|     75|  7.012|
|123456|    CAT-2|  SOUTH|   null|    100|  0.432|
|123456|    CAT-3|  NORTH|   null|     50|  5.111|
+------+---------+-------+-------+-------+-------+
所以df4看起来像

DataFrame df3 = df1.join(df2, joinCols, "right_outer");
df3.withColumn("NEW_RESULT", when(col("avgCol").isNotNull(), getResult(avgCol).otherwise(col("RESULT"))
    .drop("RESULT").withColumnRenamed("NEW_RESULT", "RESULT)
+------+---------+-------+-------+-------+-------+
|   PID| CATEGORY| REGION| avgCol| VOLUME| RESULT|
+------+-------- +-------+-------+-------+-------+
|123456|    CAT-1|  NORTH|  0.575|    200|  8.543|
|123456|    CAT-1|  SOUTH| 15.879|    125|  4.321|
|123456|    CAT-2|  NORTH|  5.255|     75|  7.012|
|123456|    CAT-2|  SOUTH|   null|    100|  0.432|
|123456|    CAT-3|  NORTH|   null|     50|  5.111|
+------+---------+-------+-------+-------+-------+
注意:我删除并重命名该列作为结果,因为我想在下一次迭代中使用此表

现在,这产生了预期的结果,但没有实现。特别是,当我将这是一个循环,并且连接列的数量不断增加时,连接和后续操作需要很长时间。每次迭代都会变得更糟

我的问题是-是否有更有效的方法在Spark中执行这两个/其中一个操作,最好使用数据帧

我读了几篇文章,建议分析join操作的物理计划,以找到优化的方法,但我从中收集不到太多信息。我不能把它包括在这里,因为它太大了。如果有人能给我指一些具体的东西,让我在实际计划中看一下,那将非常有帮助

我在一个Spark节点(单机版)上运行它-版本1.6.1。我的代码是用Java编写的。我运行这个的机器有着丰富的处理能力和内存。所以,我很确定这不是问题。非常感谢您的帮助


编辑:我正在使用从CSV文件读取基本数据df1df2是一些简单的group by+聚合的结果,我认为这不是瓶颈。

我有一个类似的问题。到目前为止,我还没有找到一个最佳的方法