我试图从[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列是多余的,但只是将其用作示例方案。
答案 0 :(得分:1)
distinct
是使用reduceByKey
实施的。实际上,您刚刚重新实现了distinct
(几乎)它的确切位置currently implemented。
但是,您的2个代码段并不相同。在
它的第一个片段
它的第二个片段
如果不同文件中存在重复的行,则它们将在第一个代码段中重复,但不会在第二个代码段中重复。这可能就是你内存不足的原因。请注意,此处不需要通过collect
调用将所有记录带到驱动程序中,这会严重影响性能