背景

定义了一个udf,用于信息解密,请求的是公司内部解密服务,解密服务部署了两台机器,随机请求。调用udf时,传入密文,输出明文。数仓每天有在用,且批量调用,没有性能问题。

最近新上线一个数据需求,发现卡在了解密udf,要30-40分钟。

原因

1.看解密服务完全没有压力,跑批的时候cpu使用率可以达到4000-5000%,现在只有100%左右。

2.看yarn资源分配也没有问题,尝试参数调优有点效果,但非常有限,解密服务的cpu还是上不去。

3.也怀疑过原始数据和udf可能存在问题,比如传了一些异常的密文导致udf异常处理失败或者重试导致耗时长。查看原始数据是否异常,udf添加日志打印,也没有问题。

4.如果跳过解密udf,任务几分钟就跑完,可以确定是调用udf导致。

原表是个分区表,数据量1578671,udf实例调用次数674326。

看表分区所读文件分布如下,总共4个文件,每个文件在150-300M左右。

[[email protected] ~]$ hdfs dfs -ls  /user/hive/warehouse/xy_snap.db/sms_db_t_sms_sended/xy_date=20191205    
Found 4 items
-rwxrwxrwt   3 hdfs hive  296733124 2019-12-09 01:41 /user/hive/warehouse/xy_snap.db/sms_db_t_sms_sended/xy_date=20191205/part-00000-4d8da335-585c-4b1a-97ad-293d8cd1e9f6-c000
-rwxrwxrwt   3 hdfs hive  255201346 2019-12-09 01:40 /user/hive/warehouse/xy_snap.db/sms_db_t_sms_sended/xy_date=20191205/part-00001-4d8da335-585c-4b1a-97ad-293d8cd1e9f6-c000
-rwxrwxrwt   3 hdfs hive  249122911 2019-12-09 01:40 /user/hive/warehouse/xy_snap.db/sms_db_t_sms_sended/xy_date=20191205/part-00002-4d8da335-585c-4b1a-97ad-293d8cd1e9f6-c000
-rwxrwxrwt   3 hdfs hive  150442190 2019-12-09 01:40 /user/hive/warehouse/xy_snap.db/sms_db_t_sms_sended/xy_date=20191205/part-00003-4d8da335-585c-4b1a-97ad-293d8cd1e9f6-c000

由于小文件有各种问题,我们平时习惯做了小文件合并,所以一般文件比较大,排除了各种可能问题,最终怀疑是几个大文件导致,那就拆分文件试试看。

解决

尝试用pyspark对该表做大文件拆分,将4个大文件拆分成1000个小文件,然后再执行任务。

from pyspark import SQLContext
from pyspark import SparkContext
from pyspark.sql import SparkSession

sc.stop()
sc = SparkSession.builder.appName("pyspark3-demo2").getOrCreate().sparkContext
print('sparkContext create success')

fileFormat = 'orc'
sqlContext = SQLContext(sc)
df = sqlContext.read.load(path='/user/hive/warehouse/xy_snap.db/sms_db_t_sms_sended/xy_date=20191205/', format=fileFormat)
df.rdd.getNumPartitions()

df.repartition(1000).write.save(path='/user/hive/warehouse/xy_snap.db/sms_db_t_sms_sended_new/xy_date=20191205/', format=fileFormat, mode='overwrite')
sc.stop()

对比前后文件,4个变成1000个

spark调用udf性能优化

验证sql

select 
    count(distinct crowd_mix_id) as num1,
    count(distinct group_index) as num2
from
(
    select
        get_json_object(cast(unbase64(a.fstrparameter) as string),'$.BDDMP_mixId') as crowd_mix_id_enc
        , xy_udf.userinfodecrypt(get_json_object(cast(unbase64(a.fstrparameter) as string),'$.BDDMP_mixId')) as crowd_mix_id     --crowd_mix_id
        , get_json_object(cast(unbase64(a.fstrparameter) as string),'$.BDDMP_group') as group_index_enc
        , xy_udf.userinfodecrypt(get_json_object(cast(unbase64(a.fstrparameter) as string),'$.BDDMP_group')) as group_index   -- crowd_mix 分组
    from xy_snap.sms_db_t_sms_sended_new a
    where a.xy_date='20191205'
    and lower(fstroriginalorderid) like '%dmp%'
) a
;

对比

验证文件拆分前后任务耗时对比

spark调用udf性能优化

资源不变的情况下,文件拆分后性能提升还是很明显的,每个小文件对应一个task,task数量增加,任务并发能力提升,从另外一个方面看,解密服务所有机器的cpu使用率提升也很明显。

相关文章: