首页 > 解决方案 > 有没有办法将 parquet 分区下的所有文件读取到单个 spark 分区上?

问题描述

数据以镶木地板格式存储。parquet 文件根据分区键列(用户 id 列的哈希值)进行分区

userData/
    partitionKey=1/
        part-00044-cf737804-90ea-4c37-94f8-9aa016f6953a.c000.snappy.parquet
        part-00044-cf737804-90ea-4c37-94f8-9aa016f6953b.c000.snappy.parquet
    partitionKey=2/
        part-00059-cf737804-90ea-4c37-94f8-9aa016f6953a.c000.snappy.parquet
    partitionKey=3/
        part-00002-cf737804-90ea-4c37-94f8-9aa016f6953a.c000.snappy.parquet

给定分区方案,我们知道:

  1. 给定用户的所有数据都将属于同一分区
  2. 一个分区可以有多个用户的数据

在读取数据时,我希望 1 个用户的所有数据都落入同一个 spark 分区。一个 spark 分区可以有多个用户,但它应该包含所有这些用户的所有行。

目前,我使用的是: SparkSession.read.parquet("../userData").repartition(200, col("UserId"))

(也尝试了使用自定义分区器的 partitionBy;操作顺序:DataFrame -> RDD -> KeyedRDD -> partitionBy -> RDD -> DataFrame;在 partitionBy 之前,有一个反序列化到对象的步骤,这会爆炸 shuffle 写入)

有没有办法避免重新分区并利用输入文件夹结构将用户的数据放在单个分区上?

标签: scalaapache-sparkpartitioningparquet

解决方案


SparkSession.read.parquet应该根据您的文件路径自动推断分区信息。你可以在这里找到更多信息

如果您的文件路径是:

userData/
    UserId=1/
        part-00044-cf737804-90ea-4c37-94f8-9aa016f6953a.c000.snappy.parquet
        part-00044-cf737804-90ea-4c37-94f8-9aa016f6953b.c000.snappy.parquet
    UserId=2/
        part-00059-cf737804-90ea-4c37-94f8-9aa016f6953a.c000.snappy.parquet
    UserId=3/
        part-00002-cf737804-90ea-4c37-94f8-9aa016f6953a.c000.snappy.parquet

当您调用SparkSession.read.parquet("/path/to/userData")时,它将按UserId.


推荐阅读