Spark读取文件生成RDD仅1个分区,如何实现分布式并行计算?
单分区原因及并行化调整方案
仅生成1个分区的核心原因
- 单文件大小未达分片阈值:
sc.textFile()默认分片大小和HDFS块(默认128MB)对齐,若你的test123.txt文件大小小于128MB,Spark默认将整个文件作为1个分片,对应1个分区。 - 本地文件系统读取限制:你使用的是本地文件路径,本地文件系统不支持随机寻址并发读取,Spark读取单个本地文件时默认不会拆分,只会生成1个分区,哪怕文件体积超过128MB。
- 未显式指定最小分区数:
textFile支持传入第二个参数作为最小分区数,未传参时Spark会优先按文件大小和存储系统特性生成分区,单本地小文件场景下默认只会生成1个分区。
实现并行运算的调整方案
你可以根据使用场景选择以下任意一种方法调整分区数:
- 读取时指定最小分区数
调用textFile时传入第二个参数指定最小分区数,示例如下:
rdd= (sc.sparkContext .textFile("./test123.txt", 4) # 最小生成4个分区 .map(lambda x: x.split("|")) )
注:原代码中的flatMap(lambda line: line.split("\n\r"))是冗余操作,textFile已经自动按换行符将文件拆分为每行一条记录,无需额外拆分。
- 读取后手动重分区
如果已经生成单分区RDD,可以调用repartition方法增加分区数(增加分区必须用repartition,减少分区用coalesce性能更高):
# 调整为4个分区 rdd = rdd.repartition(4)
- 使用更灵活的读取API
如果是结构化的分隔符文件,更推荐用Spark SQL的CSV读取接口,分区控制更灵活,还自带格式解析能力:
df = spark.read.option("sep", "|").csv("./test123.txt") rdd = df.rdd
该接口会自动根据文件大小、数量生成合理的分区数,无需手动调整。
- 集群运行适配
如果要提交到分布式集群运行,需要把输入文件上传到HDFS、S3等分布式存储系统,不要使用本地路径,这样Spark才能自动将文件切分为多个分片,分发到不同节点并行处理,并行度会自动和集群CPU核心数、文件块数对齐。
内容的提问来源于stack exchange,提问作者Infinite
相关产品推荐
相关产品推荐

