有没有办法在数据帧级别上优化dataframe.writer.partitionBy?

时间:2019-08-22 06:44:32

标签: apache-spark apache-spark-sql partitioning

如果我正确地理解了文档,则对数据框进行分区与对配置单元或其他磁盘表进行分区相比似乎有所不同。对于磁盘存储,按日期进行分区会为我的数据集中出现的每个日期创建一个分区的 set 。这似乎很有用;如果我查询给定日期的记录,则群集中的每个节点仅处理与所需日期相对应的分区。

另一方面,

Dataframe.repartition为数据集中的每个日期创建一个一个分区。如果我从特定日期搜索记录,它们都将在单个分区中找到,因此全部由单个节点处理。

这是对的吗?如果是这样,用例是什么?在数据帧的上下文中,如何获得磁盘分区方案的速度优势?

对于它的价值,我需要先 后再进行磁盘数据的聚合,因此即使延迟执行,磁盘上的分区也不一定对我有帮助。

1 个答案:

答案 0 :(得分:1)

在您的示例中,Spark将能够非常快速地恢复链接到该日期的所有记录。这是一个进步。 在下面的代码中,您可以看到该过滤器已归类为分区过滤器。

inputRdd = sc.parallelize([("fish", 1), ("cats",2), ("dogs",3)])
schema = StructType([StructField("animals", StringType(), True),
                StructField("ID", IntegerType(), True)])
my_dataframe = inputRdd.toDF(schema)
my_dataframe.write.partitionBy('animals').parquet("home")
sqlContext.read.parquet('home').filter(col('animals') == 'fish').explain()

== Physical Plan ==
*(1) FileScan parquet [ID#35,animals#36] Batched: true, DataFilters: [], Format: Parquet, Location: InMemoryFileIndex[dbfs:/home], PartitionCount: 1, PartitionFilters: [isnotnull(animals#36), (animals#36 = fish)], PushedFilters: [], ReadSchema: struct<ID:int>

要获得更深入的了解,您可能需要看看this

我实际上不确定您的其他问题。您可能是对的,在我的示例中df.rdd.getNumPartitions()给出了1。并且对于一个分区,性能并不是那么好(但是此时您已经从磁盘读取了)。对于以下步骤,调用repartition(n)将解决此问题,但代价可能很高。

另一个可能的改进与联接共享相同分区的两个数据帧(联接键为分区列)有关,您将在联接阶段避免很多洗牌。