首页 > 解决方案 > 只需过滤一次即可有效地将 Spark DataFrame 一分为二

问题描述

比方说,我们有dfSource非平凡的 Dataframe(例如,不同连接的结果等)和大尺寸(例如 100k+ 行),并且它有一个 column some_boolean,我想用它来拆分,如下所示:

val dfTrue = dfSource.where(col("some_boolean") === true)
// write dfTrue, e.g. dfTrue.write.parquet("data1")
val dfFalse = dfSource.where(col("some_boolean") === false)
// write dfFalse, e.g. dfFalse.write.parquet("data2")

现在这将导致两次扫描和过滤数据,对吧?有没有办法更有效地做到这一点?我想到了类似的东西

val (dfTrue, dfFalse) = dfSource.split(col("some_boolean") === true)
// write dfTrue and dfFalse

标签: scalaperformanceapache-spark

解决方案


我看到您在拆分后存储输出。写的时候可以使用partitionPy如下:

dfSource = spark.createDataFrame([
    ['a', True],
    ['b', False],
    ['c', True],
    ['d', True],
    ['e', False],
    ['f', False]
], ["col1", "col2"]).cache()
dfSource.show()

+----+-----+
|col1| col2|
+----+-----+
|   a| true|
|   b|false|
|   c| true|
|   d| true|
|   e|false|
|   f|false|
+----+-----+


dfSource.write.partitionBy("col2").parquet("/tmp/df")

您将看到这两个目录/tmp/df/col2=true/tmp/df/col2=false

现在你可以像往常一样阅读它们了

dfTrue = spark.read.parquet("/tmp/df/col2=true")
dfTrue.show()
+----+
|col1|
+----+
|   a|
|   c|
|   d|
+----+

dfFalse = spark.read.parquet("/tmp/df/col2=false")
dfFalse.show()
+----+
|col1|
+----+
|   b|
|   e|
|   f|
+----+

推荐阅读