分区列倾斜时,更有效地编写分区实木复合地板

时间:2019-07-10 18:03:48

标签: sql apache-spark partitioning skew

我正在用分区实木复合地板写一个大表(约1.2b行),我使用状态(如美国状态)作为分区键。问题是存在大量的空状态值。该表通常是按状态查询的,因此具有大的具有空状态的分区不是问题,但是我在更高效地生成表方面遇到了麻烦。

我尝试用非空状态创建表,然后插入空值,但是据我所知,所有空值仍然只是放在一个大分区中,并因此发送给一个工人。

如果有一种方法可以插入特定的分区,那就太好了。就像我的示例一样,编写非空状态,然后将剩余的记录插入state = null或hive_default_partition中,其方式仍然可以在整个群集中并行进行。

1 个答案:

答案 0 :(得分:0)

尝试使用自动分区写入非空数据,然后对空数据重新分区并分别写入,例如:

df.where($”state”.isNotNull).write.partitionBy($”state”).parquet(“my_output_dir”)
df.where($”state”.isNull).repartition(100).write.parquet(“my_output_dir/state=__HIVE_DEFAULT_PARTITION__”)

使用SQL API,您可以使用重新分区提示(Spark 2.4中引入)来完成相同操作:

spark-sql> describe skew_test;  
id  bigint  NULL
dt  date    NULL
state   string  NULL
# Partition Information     
# col_name  data_type   comment
state   string  NULL
Time taken: 0.035 seconds, Fetched 6 row(s)
spark-sql> CREATE TABLE `skew_test2` (`id` BIGINT, `dt` DATE, `state` STRING)
         > USING parquet
         > OPTIONS (
         >   `serialization.format` '1'
         > )
         > PARTITIONED BY (state);
Time taken: 0.06 seconds
spark-sql> insert into table skew_test2  select * from skew_test where state is not null;
Time taken: 1.208 seconds
spark-sql> insert into table skew_test2  select /*+ REPARTITION(100) */ * from skew_test where state is  null;
Time taken: 1.39 seconds

您应该看到Spark为最终声明创建了100个任务,并且您的state=__HIVE_DEFAULT_PARTITION__目录应该包含100个实木复合地板文件。有关Spark-SQL提示的更多信息,请查看https://jaceklaskowski.gitbooks.io/mastering-spark-sql/spark-sql-hint-framework.html#specifying-query-hints