如何在Spark SQL中强制进行内存中的分块排序?

时间:2016-06-05 10:16:19

标签: apache-spark

Parquet文件格式对记录顺序很敏感。其列式编码可能会产生重要的较小文件,具体取决于排序顺序。 另一方面,对TB级输入记录进行排序非常昂贵。

分成几块让我们说10GB允许内存排序,同时生成几乎一样小的镶木地板文件,好像整个1 TB完全分类一样。

是否有可能在生成镶木地板文件之前指示Spark SQL进行分块排序?

另一个用例是在编写统一的Parquet文件之前使用分块排序将许多小的Parquet文件合并为一个。

1 个答案:

答案 0 :(得分:1)

据我所知, Spark< 中没有开箱即用的选项。 2.0.0 即可。您可以尝试的一件事是在编写之前将coalesce与Hive SORT BY子句合并,这应该具有类似的效果:

val df: DataFrame = ???
val n: Int = ??? //

df.coalesce(n)
df.coalesce(n).registerTempTable("df")
sqlContext.sql("SELECT * FROM df SORT BY foo, bar").write.parquet(...)

df.coalesce(n).sortWithinPartitions($"foo", $"bar").write.parquet(...)

请注意,SORT BY不等同于DataFrame.sort

Spark 2.0.0 引入了sortBybucketBy方法,其中后者按给定列和{对每个存储桶中的输出进行排序{3}}:

val df: DataFrame = ???
val nBuckets: Int = ???

df.write.bucketBy(nBuckets, "foo").sortBy("foo", "bar").saveAsTable(...)

注意:这似乎只在使用saveAsTable保存Parquet文件时起作用,但它看起来不像{{1}中直接支持拼花拼写(df.write.bucketBy(...).sortBy(...).parquet(...)) }}