Apache spark 优化Spark作业-Spark 2.1

Apache spark 优化Spark作业-Spark 2.1,apache-spark,optimization,apache-spark-sql,spark-ui,Apache Spark,Optimization,Apache Spark Sql,Spark Ui,我的spark作业目前运行59分钟。我想优化它,这样我就可以节省时间。我注意到作业的最后一步需要花费大量时间(55分钟)(请参见下面spark UI中spark作业的屏幕截图) 我需要连接一个大数据集和一个小数据集,在这个连接的数据集上应用转换(创建一个新列) 最后,我应该根据列PSP(请参见下面的代码片段)对数据集进行重新分区。最后我还执行了排序(根据3列对每个分区进行排序) 所有详细信息(基础设施、配置、代码)都可以在下面找到 我的代码片段: spark.conf.set(“spark.sq

我的spark作业目前运行59分钟。我想优化它,这样我就可以节省时间。我注意到作业的最后一步需要花费大量时间(55分钟)(请参见下面spark UI中spark作业的屏幕截图)

我需要连接一个大数据集和一个小数据集,在这个连接的数据集上应用转换(创建一个新列)

最后,我应该根据列
PSP
(请参见下面的代码片段)对数据集进行重新分区。最后我还执行了排序(根据3列对每个分区进行排序)

所有详细信息(基础设施、配置、代码)都可以在下面找到

我的代码片段:
spark.conf.set(“spark.sql.shuffle.partitions”,4158)
val uh=uh_个月
.withColumn(“UHDIN”,datediff(to_date(unix时间戳)(col(“UHDIN,yyyyymmdd”),“yyyyymmdd”).cast(TimestampType)),
截止日期(unix时间戳(col(“一月”),“yyyy-MM-dd”).cast(TimestampType)))
“ddMMMyyyy”).cast(TimestampType)))
.带列(“DVA_1”,日期格式(列(“DVA”),“dd/MM/yyyy”))
.drop(“UHDIN_YYYYMMDD”)
.drop(“一月”)
.drop(“DVA”)
.persist()
val uh_flag_comment=new TransactionType().transform(uh)
不持久
val-uh\u-join=uh\u-flag\u-comment.join(广播(smallDF),“NO\u-NUM”)
.选择(
呃,col(“*”),
smallDF.col(“PSP”),
smallDF.col(“minrel”),
smallDF.col(“标签”),
smallDF.col(“起始日期”))
.改名为“DVA_1”,“DVA”)
smallDF.unpersist()
val uh_to_be_sorted=uh_joined.重新分区(4158列(“PSP”))
val uh_final=uh_加入。sortWithinPartitions(col(“NO_NUM”)、col(“UHDIN”)、col(“HOURMV”))
uh_决赛
编辑-重新分区逻辑
val sqlContext=spark.sqlContext
register(“randomUDF”,(partitionCount:Int)=>{
val r=新的scala.util.Random
r、 nextInt(分区计数)
//也尝试使用r.nextInt(分区计数)+col(“PSP”)
})
val uh_to_be_sorted=uh_joined
.带列(“tmp”、callUDF(“随机UDF”、lit(“4158”))
.重新分配(4158,col(“tmp”))
.下降(col(“tmp”))
val uh_final=uh_to_be_sorted.sortwith分区(col(“NO_NUM”)、col(“UHDIN”)、col(“HOURMV”))
uh_决赛
smallDF
是我广播的一个小数据集(535MB)

TransactionType
是一个类,在该类中,我根据3列(
MMED
DeCred
NMTGP
)的值向我的
uh
数据帧添加一列新的字符串元素,并使用正则表达式检查这些列的值

我以前遇到过很多问题(作业失败),因为没有找到洗牌块。我发现我正在溢出到磁盘,并且有很多GC内存问题,所以我将“spark.sql.shuffle.partitions”增加到4158

为什么是4158?
Partition\u count=(阶段输入数据)/(分区的目标大小)

所以
Shuffle partition\u count=(Shuffle stage输入数据)/200 MB=860000/200=4300

我有可用的
16*24-6=378个内核
。因此,如果我想一次性运行每个任务,我应该将4300除以378,大约是11。然后11*378=4158

Spark版本:2.1 群集配置:
  • 24个计算节点(工作节点)
  • 每个16个V孔
  • 每个节点90 GB RAM
  • 6个内核已被其他进程/作业使用
当前火花配置: -大师:纱线

-执行器存储器:26G

-执行器核心:5

-驱动器存储器:70G

-执行人数:70

-spark.kryoserializer.buffer.max=512

-火花驱动磁芯=5

-spark.driver.maxResultSize=500m

-spark.memory.storageFraction=0.4

-spark.memory.fraction=0.9

-spark.hadoop.fs.permissions.umask mode=007

作业是如何执行的: 我们使用IntelliJ构建一个工件(jar),然后将其发送到服务器。然后执行一个bash脚本。此脚本:

  • 导出一些环境变量(SPARK\u HOME、HADOOP\u CONF\u DIR、PATH和SPARK\u LOCAL\u DIRS)

  • 使用上面spark配置中定义的所有参数启动spark submit命令

  • 检索应用程序的纱线日志

Spark用户界面截图 DAG

@Ali

根据汇总指标,我们可以说您的数据有偏差(最大持续时间:49分钟,最大随机读取大小/记录:2.5 GB/23947440,其中平均需要4-5分钟,处理的行数不到200 MB/1.2 MM)

现在我们知道问题可能是少数分区中的数据倾斜,我想我们可以通过更改重新分区逻辑
val uh_to_be_sorted=uh_joined.repartition(4158,col(“PSP”)
来解决这个问题,方法是选择一些内容(如其他列或向PSP添加任何其他列)

关于数据倾斜和修复的链接很少


希望这有帮助

平均而言,您的任务执行大约需要5分钟,但您有一个需要49分钟的异常值。这是数据偏斜的症状。感谢@Gelerion,我将调查itThanks@Naga,我认为我的数据确实在我的分区之间分布不均匀。您知道我是否可以使用Spark dataframes的特定函数来执行任务吗否则,我会考虑编写一个自定义分区器,在分区之间均匀分布数据,每次我使用的分区太大时都会更改哈希值。这有意义吗?你知道如何使用数据帧来实现吗?@Ali,你可以试试这个
val r=new scala.util.Random val uh_to_be_sorted=uh_joined.withColumn(“tmp”,col(“PSP”)+r.nextInt(4158))。重新分区(4158,col(“tmp”))。删除(col(“tmp”)
;我在这里尝试的是引入一个随机数(我在这里添加,你可以做任何你喜欢的事情),然后在新列上重新分区