Apache spark 优化Spark读写性能

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

我有大约12K个二进制文件,每个文件大小为100mb,包含多个长度为变量的压缩记录。我正试图找到最有效的方式来阅读它们,解压缩,然后以拼花地板的形式写回。我的集群有6个节点,每个节点有4个核心

现在,使用下面的伪代码,读取所有文件大约需要8小时,而写回拼花地板的速度非常慢

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")
在这里选择6000
sc.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(“二进制文件”)
在没有任何错误指示的情况下卡住了。