Spark:读取文件分区数目的一些思考

本文讨论了在Spark项目中遇到的问题,即在读取阿里云OSS上的Parquet文件并按accountId写入时,分区结构与预期不符。通过研究发现,Spark的内存分区和磁盘分区概念是关键,内存分区由`repartition`和`coalesce`操作调整,磁盘分区受`partitionBy`影响。Spark默认会合并小文件,根据文件大小和打开文件的开销计算,得出内存分区数为212。理解这些机制有助于优化Spark的文件读取和分区策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在项目中遇到一个问题:在阿里云 oss 上有一些 parquet 文件,这些文件是按照 accountId 进行 partitionBy 写入的,有多个 accountId 对应的目录,总共有 4927 个 parquet 文件,总大小约为 7.3GB。但是使用 Spark 读取然后按 accountId partitionBy 写出去的文件结构跟原来的不一致,而预期是原样读取然后原样写出去。

查阅了相关资料,发现 Spark 有内存分区和磁盘分区的概念,其中 coalesce()repartition() 改变的是内存分区,partitionBy() 改变的是磁盘分区,反映在磁盘中的目录上,每一个内存分区中的数据会按 partitionBy() 分区写到磁盘上。

oss 上的 parquet 文件是使用 MongoSpark 从 MongoDB 中加载的,使用 Dataset.rdd().getNumPartitions() 查看内存分区数为 500 多,而读取这些 parquet 文件之后得到的内存分区数却为 212。

查阅资料得知,可能与 FileSourceStrategy.scala 中的逻辑有关,但是 2.4.x 版本中相关逻辑被抽到了 DataSourceScanExec.scala 中。查看源码:Spark 会对读取到的文件进行重新切分&#

### Spark 读取多个分区数据的方法及实现方式 在 Spark 中,可以通过多种方法来读取并操作分布在不同分区中的数据。以下是具体说明: #### 方法一:通过 `textFile` 设置自定义分区数 当使用 `sc.textFile(path, minPartitions)` 方法时,可以指定最小的分区数量 `minPartitions` 来控制文件被划分为多少个分区[^4]。如果未设置该参数,则默认会根据 HDFS 块大小或者本地文件系统的配置自动计算分区数目。 示例代码如下: ```scala val conf: SparkConf = new SparkConf().setMaster("local").setAppName("wordcount") val sc: SparkContext = new SparkContext(conf) // 将输入文件按照两个分区加载到 RDD 中 val rdd: RDD[String] = sc.textFile("datas/1.txt", 2) rdd.saveAsTextFile("output") ``` #### 方法二:利用 `wholeTextFiles` 处理多文件场景 对于需要一次性读取目录下所有文件的情况,推荐使用 `wholeTextFiles()` 函数。它不仅能够返回每条记录的内容字符串,还会附加对应的文件名作为键值对形式存储于 RDD 当中[^2]。 下面是一个简单的例子展示其用法: ```scala val fileRdd: RDD[(String, String)] = sc.wholeTextFiles("/path/to/directory/") fileRdd.foreach { case (fileName, content) => println(s"FileName:$fileName\nContent:\n$content") } ``` #### 方法三:基于 HashPartitioner 自动分发数据至各 Partition 假如应用层面希望手动干预如何把 Key 映射到特定的 Partition 上去的话,那么就可以采用类似于这样的逻辑表达式来进行定制化设计——即 partition index 计算公式为 `(key.hashCode() % numPartitions)`[^1] 。此策略广泛应用于诸如 Join 或 GroupByKey 这样的 Transformation 操作之中。 需要注意的是,在实际开发过程中应当充分考虑业务需求以及性能调优等因素后再决定采取何种具体的方案实施。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值