Pyspark:如何使用reduceByKey()获得唯一值对? (不使用Distinct()方法)

时间:2018-02-07 20:10:05

标签: pyspark unique distinct aggregation reduce

我试图从[1,2,3]的多个列中获取唯一值对。 数据大小非常大,有多个文件(总大小约为1TB)。

我只是想用" client"来过滤这些行。 string和grep [1,2,3]中每个文件中唯一的列。 我首先使用了元组和Distinct()函数,但是进程因Java内存错误而停止。

if __name__ == "__main__":
    sc=SparkContext(appName="someapp")
    cmd = 'hdfs dfs -ls /user/path'.split()
    files = subprocess.check_output(cmd).strip().split('\n')
    rdds=[]
    for ff in files[1:]:
        rdd=sc.textFile(ff.split()[-1])
        rdd2=rdd.filter(lambda x: "client" in x.lower())
        rdd3=rdd2.map(lambda x: tuple(x.split("\t")[y] for y in [1,2,3]))
        rdd4=rdd3.distinct()
        rdds.append(rdd4)

     rdd0=sc.union(rdds)
     rdd0.collect()
     rdd0.saveAsTextFile('/somedir')

所以我尝试了另一种使用reduceByKey()方法的脚本,效果很好。

if __name__ == "__main__":
        sc=SparkContext(appName="someapp")
        cmd = "hdfs dfs -ls airties/eventU".split()
        files = subprocess.check_output(cmd).strip().split('\n')
        rdds=[]
        for ff in files[1:]:
                rdd=sc.textFile(ff.split()[-1])
                rdd2=rdd.filter(lambda x: "client" in x.lower())
                rdd3=rdd2.map(lambda x: ','.join([x.split("\t")[y] for y in [1,2,3]]))
                rdds.append(rdd3)
        rdd0=sc.union(rdds)
        rddA=rdd0.map(lambda x: (x,1)).reduceByKey(lambda a,b: a+b)
        rddA.collect()
        rddA.saveAsTextFile('/somedir')

但我尝试理解为什么Distinct()效果不佳,但reduceByKey()方法有效。 distinct()不是找到唯一值的正确方法吗?

还试图找到一种更好的方法来优化多个文件的处理,在每个文件中查找唯一值对并聚合它们。当每个文件包含独占内容时,我只需要对每个文件应用唯一,并在最后一步中完全聚合。但似乎我当前的代码为系统带来了太多的开销。

数据是这样的:很多冗余

+-----+---+------+----------+
|1    |2  |3     |4         |
+-----+---+------+----------+
|    1|  1|     A|2017-01-01|
|    2|  6|client|2017-01-02|
|    2|  3|     B|2017-01-02|
|    3|  5|     A|2017-01-03|
|    3|  5|client|2017-01-03|
|    2|  2|client|2017-01-02|
|    3|  5|     A|2017-01-03|
|    1|  3|     B|2017-01-02|
|    3|  5|client|2017-01-03|
|    3|  5|client|2017-01-04|
+-----+---+------+----------+

数据是这样的:很多冗余

+-----+---+------+
|1    |2  |3     |
+-----+---+------+
|    2|  6|client|
|    3|  5|client|
|    2|  2|client|
|    3|  5|client|
|    3|  5|client|
+-----+---+------+

第3列是多余的,但只是将其用作示例方案。

1 个答案:

答案 0 :(得分:1)

distinct是使用reduceByKey实施的。实际上,您刚刚重新实现了distinct(几乎)它的确切位置currently implemented

但是,您的2个代码段并不相同。在

它的第一个片段

  • 处理RDD
  • 保存RDD的不同元素
  • 将RDD附加到列表,以便稍后创建聚合RDD

它的第二个片段

  • 处理RDD
  • 将RDD附加到列表,以便稍后创建聚合RDD
  • 在聚合RDD中保存不同的元素

如果不同文件中存在重复的行,则它们将在第一个代码段中重复,但不会在第二个代码段中重复。这可能就是你内存不足的原因。请注意,此处不需要通过collect调用将所有记录带到驱动程序中,这会严重影响性能