Pyspark 使用迭代Spark数据帧创建的内存错误

Pyspark 使用迭代Spark数据帧创建的内存错误,pyspark,Pyspark,我正在将一个zlib压缩文件中的原始记录转换为丰富的拼花地板记录,以便稍后在Spark中进行处理。我不控制zlib文件,我需要与其他处理一致的拼花地板。我在Pyspark和Spark 2.3中工作。我的方法有效,除非zlib文件相当大(~300MB)。它可以很好地保存在内存中,但Spark的内存不足。如果我把我的驱动程序内存往上推(8g),它就会工作。它感觉像是使用函数调用导致的内存泄漏,如下所示 扩展过程会在Spark中爆炸数据,因此我使用迭代数据帧创建和适当大小的驱动程序内存(默认为4g)。

我正在将一个zlib压缩文件中的原始记录转换为丰富的拼花地板记录,以便稍后在Spark中进行处理。我不控制zlib文件,我需要与其他处理一致的拼花地板。我在Pyspark和Spark 2.3中工作。我的方法有效,除非zlib文件相当大(~300MB)。它可以很好地保存在内存中,但Spark的内存不足。如果我把我的驱动程序内存往上推(8g),它就会工作。它感觉像是使用函数调用导致的内存泄漏,如下所示

扩展过程会在Spark中爆炸数据,因此我使用迭代数据帧创建和适当大小的驱动程序内存(默认为4g)。我将所有原始解压文件加载到内存中,然后将其中的一块传递给一个简单的例程,以创建spark数据帧,通过充实过程添加列,然后写入parquet。块的大小是固定的。扩展本身可能会有所不同,但我相信,总的来说,块大小不应该在驱动程序中创建太大的数据帧。拼花格式的输出块大约为100MB

def process_file(gzfile, spark, chunk_size=2000000):
    # load_data_and decompress
    data = load_original_data(gzfile)
    if len(data) == 0:
        raise ValueError("No records loaded from file ", gzfile)
    chunks = len(data) // chunk_size + 1
    offset = 0
    for chunk in range(chunks):
        # convert the chunk into a spark dataframe 
        df = raw_to_spark(data[offset:offset+chunk_size], spark)
        offset += chunk_size
        # enrich the data while in a spark dataframe w/ more columns
        df = extract_fields_from_raw(df)
        save_to_parquet(df, parquet_output_path)
    return 


def raw_to_spark(events: List[str], spark: pyspark.sql.SparkSession) -> pyspark.sql.DataFrame:
    """
    convert the list of raw strings into a spark dataframe so we can do all the processing. this list is large in
    memory so we pop one list while building the new one. then throw the new list into spark. 
"""
    schema = StructType([StructField("event", StringType())])
    rows = []  # make the list smaller as we create the row list for the dataframe
    while events:
        event = events.pop()
        if event.count(",") >= 6:  # make sure there are 7 fields at least
            rows.append(pyspark.sql.Row(event))
    rdd = spark.sparkContext.parallelize(rows, numSlices=2000)  # we need to partition in order to pass to workers
    return spark.createDataFrame(rdd, schema=schema)

def extract_fields_from_raw(df: pyspark.sql.DataFrame) -> pyspark.sql.DataFrame:
"""
this adds columns to the dataframe for enrichment before saving
"""

那么,Spark dataframes的大小您是否尝试使用行生成器而不是列表(即创建一个执行while事件循环并使用yield的函数)?否,我只关注它的Spark部分。让我想想这会有什么帮助。。我明白你的意思。。我仍然需要生成一个大的N,以便执行spark数据帧。很久以前,我尝试通过迭代添加行来创建它们;那很糟糕。