Apache spark 优化Spark读写性能
我有大约12K个二进制文件,每个文件大小为100mb,包含多个长度为变量的压缩记录。我正试图找到最有效的方式来阅读它们,解压缩,然后以拼花地板的形式写回。我的集群有6个节点,每个节点有4个核心 现在,使用下面的伪代码,读取所有文件大约需要8小时,而写回拼花地板的速度非常慢Apache spark 优化Spark读写性能,apache-spark,pyspark,Apache Spark,Pyspark,我有大约12K个二进制文件,每个文件大小为100mb,包含多个长度为变量的压缩记录。我正试图找到最有效的方式来阅读它们,解压缩,然后以拼花地板的形式写回。我的集群有6个节点,每个节点有4个核心 现在,使用下面的伪代码,读取所有文件大约需要8小时,而写回拼花地板的速度非常慢 def reader(file_name): keyMsgList = [] with open(file_name, "rb") as f: while True: h
def reader(file_name):
keyMsgList = []
with open(file_name, "rb") as f:
while True:
header = f.read(12)
if not header:
break
keyBytes = header[0:8]
msgLenBytes = header[8:12]
# conver keyBytes & msgLenBytes to int
message = f.read(msgLen)
keyMsgList.append((key, decode(message)))
return keyMsgList
files = os.listdir("/path/to/binary/files")
rddFiles = sc.parallelize(files, 6000)
df = spark.createDataFrame(rddFiles.flatMap(reader), schema)
df.repartition(6000).write.mode("append").partitionBy("key").parquet("/directory")
在这里选择6000sc.parallelize(files,6000)
背后的理性是创建每个200 MB大小的分区,即(12k文件*100mb大小)/200MB
。由于文件内容的顺序性,需要逐字节读取,因此不确定是否可以进一步优化读取?
类似地,当写回拼花地板时,重新分区(6000)
中的数字是为了确保数据均匀分布,并且所有执行者都可以并行写入。然而,这是一个非常缓慢的操作
一种解决方案是增加执行器的数量,这将提高读取性能,但不确定是否会提高写入性能
在这里寻找如何改进性能的建议?建议1:不要使用重新分区
,而是使用合并
。
看。您发现了重新分区操作的瓶颈,这是因为您启动了一次完全洗牌。使用合并
时,您不会这样做。您也将得到N个分区。它们不会像您通过重新分区得到的那样平衡,但这有关系吗
我建议您支持合并
而不是重新分区
建议2:6000个分区可能不是最优的
应用程序使用6个节点和4个核心运行。您有6000个分区。这意味着您有大约250个核心分区(甚至不包括提供给主分区的分区)。在我看来,这太过分了
由于您的分区很小(大约200Mb),您的主分区可能会花费比执行查询更多的时间等待来自executor的Anwser
我建议您减少分区的数量
建议3:您可以使用DataFrameAPI吗?
数据帧API操作通常比手工编码的解决方案更快、更好
也许可以看看pyspark.sql.functions
,看看是否可以在那里找到一些东西(请参阅)。我不知道这是否相关,因为我没有看到您的数据,但根据我的经验,这是我的一般建议。我考虑了分区的数量,即6k可能太高,但担心分区越少可能会导致内存溢出,就像读取文件一样。关于DFAPI,问题是spark.read.format(“二进制文件”)
在没有任何错误指示的情况下卡住了。