Parquet文件格式对记录顺序很敏感。其列式编码可能会产生重要的较小文件,具体取决于排序顺序。 另一方面,对TB级输入记录进行排序非常昂贵。
分成几块让我们说10GB允许内存排序,同时生成几乎一样小的镶木地板文件,好像整个1 TB完全分类一样。
是否有可能在生成镶木地板文件之前指示Spark SQL进行分块排序?
另一个用例是在编写统一的Parquet文件之前使用分块排序将许多小的Parquet文件合并为一个。
答案 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 引入了sortBy
和bucketBy
方法,其中后者按给定列和{对每个存储桶中的输出进行排序{3}}:
val df: DataFrame = ???
val nBuckets: Int = ???
df.write.bucketBy(nBuckets, "foo").sortBy("foo", "bar").saveAsTable(...)
注意:这似乎只在使用saveAsTable
保存Parquet文件时起作用,但它看起来不像{{1}中直接支持拼花拼写(df.write.bucketBy(...).sortBy(...).parquet(...)
) }}