SparkSQL - 加入后得到重复的行&通过...分组

时间:2018-01-27 10:38:48

标签: apache-spark apache-spark-sql spark-dataframe

我有两个带有列的数据框,如下所示 注意:列uid 不是唯一键,并且数据框中存在具有相同uid的重复行。

val df1 = spark.read.parquet(args(0)).drop("sv")
val df2 = spark.read.parquet(args(1))

scala> df1.orderBy("uid").show

+----+----+---+
| uid| hid| sv|
+----+----+---+
|uid1|hid2| 10|
|uid1|hid1| 10|
|uid1|hid3| 10|
|uid2|hid1|  2|
|uid3|hid2| 10|
|uid4|hid2|  3|
|uid5|hid3|  5|
+----+----+---+

scala> df2.orderBy("uid").show

+----+----+---+
| uid| pid| sv|
+----+----+---+
|uid1|pid2|  2|
|uid1|pid1|  1|
|uid2|pid1|  2|
|uid3|pid1|  3|
|uid3|pidx|999|
|uid3|pid2|  4|
|uidx|pid1|  2|
+----+----+---+

scala> df1.drop("sv")
  .join(df2, "uid")
  .groupBy("hid", "pid")
  .agg(count("*") as "xcnt", sum("sv") as "xsum", avg("sv") as "xavg")
  .orderBy("hid").show

+----+----+----+----+-----+
| hid| pid|xcnt|xsum| xavg|
+----+----+----+----+-----+
|hid1|pid1|   2|   3|  1.5|
|hid1|pid2|   1|   2|  2.0|
|hid2|pid2|   2|   6|  3.0|
|hid2|pidx|   1| 999|999.0|
|hid2|pid1|   2|   4|  2.0|
|hid3|pid1|   1|   1|  1.0|
|hid3|pid2|   1|   2|  2.0|
+----+----+----+----+-----+

在这个演示案例中,一切看起来都不错。

但是当我对生产大数据应用相同的操作时,最终输出包含许多重复行(相同(hid, pid)对)
我虽然groupBy运算符会像select distinct hid, pid from ...,但显然不是。hid, pid

那我的手术有什么问题?我应该按.drop("uid")重新分区数据框吗? 谢谢!

- 更新
如果我在加入数据帧后添加scala> df1.drop("sv") .join(df2, "uid").drop("uid") .groupBy("hid", "pid") .agg(count("*") as "xcnt", sum("sv") as "xsum", avg("sv") as "xavg") .orderBy("hid").show ,则会从最终输出中遗漏一些行。

class timeAgo {

static String getTimeAgo(long time_ago) {
    time_ago=time_ago/1000;
    long cur_time = (Calendar.getInstance().getTimeInMillis())/1000 ;
    long time_elapsed = cur_time - time_ago;
    long seconds = time_elapsed;
   // Seconds
    if (seconds <= 60) {
        return "Just now";
    }
    //Minutes
    else{
        int minutes = Math.round(time_elapsed / 60);

        if (minutes <= 60) {
            if (minutes == 1) {
                return "a minute ago";
            } else {
                return minutes + " minutes ago";
            }
        }
        //Hours
        else {
            int hours = Math.round(time_elapsed / 3600);
            if (hours <= 24) {
                if (hours == 1) {
                    return "An hour ago";
                } else {
                    return hours + " hrs ago";
                }
            }
            //Days
            else {
                int days = Math.round(time_elapsed / 86400);
                if (days <= 7) {
                    if (days == 1) {
                        return "Yesterday";
                    } else {
                        return days + " days ago";
                    }
                }
                //Weeks
                else {
                    int weeks = Math.round(time_elapsed / 604800);
                    if (weeks <= 4.3) {
                        if (weeks == 1) {
                            return "A week ago";
                        } else {
                            return weeks + " weeks ago";
                        }
                    }
                    //Months
                    else {
                        int months = Math.round(time_elapsed / 2600640);
                        if (months <= 12) {
                            if (months == 1) {
                                return "A month ago";
                            } else {
                                return months + " months ago";
                            }
                        }
                        //Years
                        else {
                            int years = Math.round(time_elapsed / 31207680);
                            if (years == 1) {
                                return "One year ago";
                            } else {
                                return years + " years ago";
                            }
                        }
                    }
                }
            }
        }
    }

}

}

2 个答案:

答案 0 :(得分:0)

老实说,我认为数据存在问题,而不是代码。当然,如果df1.drop( "sv" ) .join(df2, "uid") .groupBy( "hid", "pid" ) .agg( collect_list( "uid" ), collect_list( "sv" ) ) .orderBy( "hid" ) .show uid真的不同,我不应该有任何重复(我之前在数据中看到过一些流氓西里尔符号)。

要调试此问题,您可以尝试查看“uid”和{{1}}值的哪些组合代表每个重复的行。

{{1}}

之后,您将有一些评估数据的起点。或者,如果{{1}}(和'sv')的列表相同,则提交错误。

答案 1 :(得分:0)

我想我可能找到了根本原因。

可能这是由AWS S3一致性模型引起的。

背景是,我提交了2个Spark作业来创建2个表,并提交了第三个任务来加入这两个表(我将它们分开以防它们中的任何一个失败而且我不需要重新运行它们)。
我将这3个spark-submit放在一个按顺序运行的shell脚本中,并得到重复行的结果 当我刚刚重新完成上一份工作时,结果似乎很好。