Scala 过滤RDD中的空分区
有没有办法过滤RDD中的空分区?分区后我有一些空分区,我不能在action方法中使用它们Scala 过滤RDD中的空分区,scala,apache-spark,filtering,rdd,partition,Scala,Apache Spark,Filtering,Rdd,Partition,有没有办法过滤RDD中的空分区?分区后我有一些空分区,我不能在action方法中使用它们 我在Scala中使用ApacheSpark根据您提供的一些信息,我可以考虑两种选择。使用mapPartitions捕获空迭代器并返回它们,同时处理非空迭代器 rdd.mapPartitions{case iter=>if(iter.isEmpty){iter}else{???} 或者您可以使用重新分区,以清除空分区 rdd.repartition(10)//或任何正确的数字 如果您不知道列中的不同值,并且
我在Scala中使用ApacheSpark根据您提供的一些信息,我可以考虑两种选择。使用
mapPartitions
捕获空迭代器并返回它们,同时处理非空迭代器
rdd.mapPartitions{case iter=>if(iter.isEmpty){iter}else{???}
或者您可以使用重新分区
,以清除空分区
rdd.repartition(10)//或任何正确的数字
如果您不知道列中的不同值,并且希望避免使用空分区,则可以使用countapproxdistinc()
作为:
df.repartition(df.rdd.countApproxDistinct().toInt)
如果希望过滤现有的空分区并重新分区,可以使用Sasa建议的解决方案
或:
但是,在以后的情况下,分区可能包含也可能不包含值记录。这是我的示例数据
val sc = spark.sparkContext
val myDataFrame = spark.range(20).toDF("mycol").repartition($"mycol")
myDataFrame.show(false)
输出:
+-----+
|mycol|
+-----+
|19 |
|0 |
|7 |
|6 |
|9 |
|17 |
|5 |
|1 |
|10 |
|3 |
|12 |
|8 |
|11 |
|2 |
|4 |
|13 |
|18 |
|14 |
|15 |
|16 |
+-----+
nonEmptyPart : 20
df.rdd.partitions.length : 200
finalDf.rdd.partitions.length : 20
在上面的代码中,当您对列进行重新分区时,将创建200个分区,因为spark.sql.shuffle.partitions=200
,其中许多分区没有使用,或者是空分区,因为数据只有10个数字(我们正试图将20个数字放入200个分区中,这意味着……大多数分区都是空的……-)
1) 准备一个长累加器变量以快速计数非空分区。2) 将所有非空分区添加到累加器变量中,如下例所示
- 删除非空分区(意味着合并它们…减少洗牌/最小洗牌)
- 打印出来
+-----+
|mycol|
+-----+
|19 |
|0 |
|7 |
|6 |
|9 |
|17 |
|5 |
|1 |
|10 |
|3 |
|12 |
|8 |
|11 |
|2 |
|4 |
|13 |
|18 |
|14 |
|15 |
|16 |
+-----+
nonEmptyPart : 20
df.rdd.partitions.length : 200
finalDf.rdd.partitions.length : 20
所有非空分区都已删除的证明。。。
按分区打印的记录计数结果:
+-----------+-----+
|partitionId|count|
+-----------+-----+
|128 |1 |
|190 |1 |
|140 |1 |
|164 |1 |
|5 |1 |
|154 |1 |
|112 |1 |
|107 |1 |
|4 |1 |
|49 |1 |
|69 |1 |
|77 |1 |
|45 |1 |
|121 |1 |
|143 |1 |
|58 |1 |
|11 |1 |
|150 |1 |
|68 |1 |
|116 |1 |
+-----------+-----+
注意:
- 用法
仅用于演示/调试目的,不用于生产目的spark\u partition\u id
- 我将200个分区(由于列上的重新分区)减少为20个非空分区
最后,您摆脱了没有任何数据的额外空分区,并避免了在空分区上进行不必要的虚拟任务调度。为什么不能使用分区。你能展示整个代码和工作流程吗?什么样的操作只考虑分区?用完整的例子检查我的答案。根据示例,只有非空分区可以存在。现在,您的操作不能应用于空分区requested@UninformedUser我正在运行其他工具处理分割的文件。我不能使用空分区,因为工具会抛出异常:从stdin获取数据的工具会在运行时抛出异常empty@Patrice333这看起来更像是那些工具的问题,而不是你的问题,应该在这些工具中解决。你想知道它是否有用吗?是的,这是我使用的解决方案。但我的分区是拆分的文件,所以合并方法会大大增加处理时间。若要忽略操作中的空分区以及任务中不必要的工作,请执行以下操作。您必须/应该执行合并或重新分区(非空分区)我必须处理已分区的rdd,而不是分区,所以第一个选项对我不好。但是第二,它增加了很多处理时间。我用了colesce(),但对我不好
myDataFrame.withColumn("partitionId", org.apache.spark.sql.functions.spark_partition_id)
.groupBy("partitionId")
.count
.show
+-----------+-----+
|partitionId|count|
+-----------+-----+
|128 |1 |
|190 |1 |
|140 |1 |
|164 |1 |
|5 |1 |
|154 |1 |
|112 |1 |
|107 |1 |
|4 |1 |
|49 |1 |
|69 |1 |
|77 |1 |
|45 |1 |
|121 |1 |
|143 |1 |
|58 |1 |
|11 |1 |
|150 |1 |
|68 |1 |
|116 |1 |
+-----------+-----+