spark小文件处理

  • 一、问题
  • 二、解决思路
  • 2.1 spark 计数方式
  • 2.2 计数部分代码实现
  • 2.3 性能影响评估
  • 三、总结


一、问题

某个需求流程处理在上传s3阶段会使用spark 计算写入的数据,但是由于spark写入时是使用的默认分区200,虽然部分数据进行了分区数的处理,但是分区数效果不好。还是会存在几G或者更小十几M每个文件的情况,希望的是有一个通用的处理方式。

二、解决思路

使用spark 数据缓存,再通过去拿执行计划的缓存大小计算spark写入时所需的分区数!

2.1 spark 计数方式

由于希望有一个通用的处理方式,所以直接采用侵入spark 代码的方式进行处理
大致执行逻辑:

  1. 缓存spark df
  2. 执行计数
  3. 拿取执行计划缓存的df 大小
  4. 根据大小计算spark 合适的分区数
    可能发生的问题,由于会侵入spark代码,所以会影响spark 处理性能,后续会针对不同数据情况分别查看spark执行的性能情况。

2.2 计数部分代码实现

from pyspark.sql import DataFrame as SparkDataFrame


def is_empty(df: SparkDataFrame):
    df_result = None
    try:
        df_result = df.head()
    except:
        logging.warning("df.head() 存在异常!")
    if df_result:
        return False
    else:
        return True


def get_partition_num(df: SparkDataFrame, split_size=128, ra=1):
    '''
    df: spark  需要写入的DataFrame
    split_size: 文件大小,hdfs块大小 128M
    ra: 压缩比率
    return 分区数
    '''
    if not is_empty(df):
        df.cache()
        df.count()
        catalyst_plan = df._jdf.queryExecution().logical()
        df_size_bytes = spark._jsparkSession.sessionState().executePlan(
            catalyst_plan).optimizedPlan().stats().sizeInBytes()
        df.unpersist()
        return (df_size_bytes // 1024 // 1024 // split_size // ra) + 1
    else:
        return 40
        
df = spark.sql(exe_sql)
partition_file_num = get_partition_num(df)
spark.sql(f'''
    INSERT OVERWRITE table {self.result_table}
    SELECT 
        /*+ REPARTITION({partition_file_num}) */
        * 
    FROM result_all
''')

2.3 性能影响评估

选了一些数据,进行spark执行性能评估,执行逻辑忽略了,直接上结果。
数据1:KB级别

未改动

改动后

产出文件数

200

1

文件大小

100K左右

11M左右

执行时间

4Min

4Min

数据1:MB级别

未改动

改动后

产出文件数

200

2

文件大小

1M左右

100M左右

执行时间

4Min

3.5Min

数据1:MB级别

未改动

改动后

产出文件数

200

48

文件大小

1M左右

128M左右

执行时间

10Min

8Min

数据1:MB级别

未改动

改动后

产出文件数

200

312

文件大小

200M左右左右

128M左右

执行时间

18Min

18Min

数据1:GB级别

未改动

改动后

产出文件数

200

1129

文件大小

1.3G左右左右

128M左右

执行时间

30Min

36Min

三、总结

当批次数据量越大,count 计数的影响越明显,导致数据处理越慢。数据量小时,反而对执行有一定的促进作用,或者说几乎没有负面影响!