sparksql小文件的处理以及其他优化

 调优参数:

Spark SQL的表中,经常会存在很多小文件(大小远小于HDFS块大小),每个小文件默认对应Spark中的一个Partition,也就是一个Task。在很多小文件场景下,Spark会起很多Task。当SQL逻辑中存在Shuffle操作时,会**增加hash分桶数,严重影响性能。

在小文件场景下,您可以通过如下配置手动指定每个Task的数据量(Split Size),确保不会产生过多的Task,提高性能。

当SQL逻辑中不包含Shuffle操作时,设置此配置项,不会有明显的性能提升。

参数

描述

默认值

spark.sql.small.file.combine

用于设置是否开启小文件优化。“true”表示开启。开启后,可以避免过多的小Task。

false

spark.sql.small.file.split.size

合并小文件后,用于指定单个Task期望的数据量。

单位:Byte

256000000

 set spark.default.parallelism = 400;

/*+ coalesce(40) */    调整最后的task个数;

SELECT age, name FROM person DISTRIBUTE BY age;//按照某个字段重新分区重新分区。

对于使用动态分区的任务,使用distribute by。

insert overwrite table dm.dm_grw_retain_abtest_sd partition (year, month, day, retain_days)
select ……
distribute by retain_days -- 最终每个子分区一个文件
distribute by retain_days, cast(rand()*7 as int) -- 最终每个子分区7个文件

spark.shuffle.consolidateFiles

默认值:false

参数说明:如果使用HashShuffleManager,该参数有效。如果设置为true,那么就会开启consolidate机制,会大幅度合并shuffle write的输出文件,对于shuffle read task数量特别多的情况下,这种方法可以极大地减少磁盘IO开销,提升性能。

调优建议:如果的确不需要SortShuffleManager的排序机制,那么除了使用bypass机制,还可以尝试将spark.shffle.manager参数手动指定为hash,使用HashShuffleManager,同时开启consolidate机制。在实践中尝试过,发现其性能比开启了bypass机制的SortShuffleManager要高出10%~30%。

buffer 32k    //缓冲区默认大小为32k  SparkConf.set("spark.shuffle.file.buffer","64k")

reduce 48M //reduce端拉取数据的时候,默认大小是48M  

SparkConf.set("spark.reducer.maxSizeInFlight","96M")

    

spark.shuffle.file.buffer

默认值:32k

参数说明:该参数用于设置shuffle write task的BufferedOutputStream的buffer缓冲大小。将数据写到磁盘文件之前,会先写入buffer缓冲中,待缓冲写满之后,才会溢写到磁盘。

调优建议:如果作业可用的内存资源较为充足的话,可以适当增加这个参数的大小(比如64k),从而减少shuffle write过程中溢写磁盘文件的次数,也就可以减少磁盘IO次数,进而提升性能。在实践中发现,合理调节该参数,性能会有1%~5%的提升。

spark.reducer.maxSizeInFlight

默认值:48m

参数说明:该参数用于设置shuffle read task的buffer缓冲大小,而这个buffer缓冲决定了每次能够拉取多少数据。

调优建议:如果作业可用的内存资源较为充足的话,可以适当增加这个参数的大小(比如96m),从而减少拉取数据的次数,也就可以减少网络传输的次数,进而提升性能。在实践中发现,合理调节该参数,性能会有1%~5%的提升。

错误:reduce oom

reduce task去map拉数据,reduce 一边拉数据一边聚合   reduce段有一块聚合内存(executor memory * 0.2)

解决办法:1、增加reduce 聚合的内存的比例  设置spark.shuffle.memoryFraction

2、 增加executor memory的大小  --executor-memory 5G

3、减少reduce task每次拉取的数据量  设置spark.reducer.maxSizeInFlight  24m

spark.shuffle.io.maxRetries

默认值:3

参数说明:shuffle read task从shuffle write task所在节点拉取属于自己的数据时,如果因为网络异常导致拉取失败,是会自动进行重试的。该参数就代表了可以重试的最大次数。如果在指定次数之内拉取还是没有成功,就可能会导致作业执行失败。

调优建议:对于那些包含了特别耗时的shuffle操作的作业,建议增加重试最大次数(比如60次),以避免由于JVM的full gc或者网络不稳定等因素导致的数据拉取失败。在实践中发现,对于针对超大数据量(数十亿~上百亿)的shuffle过程,调节该参数可以大幅度提升稳定性。

shuffle file not find    taskScheduler不负责重试task,由DAGScheduler负责重试stage

spark.shuffle.io.retryWait

默认值:5s

参数说明:具体解释同上,该参数代表了每次重试拉取数据的等待间隔,默认是5s。

调优建议:建议加大间隔时长(比如60s),以增加shuffle操作的稳定性。

spark.shuffle.memoryFraction

默认值:0.2

参数说明:该参数代表了Executor内存中,分配给shuffle read task进行聚合操作的内存比例,默认是20%。

调优建议:在资源参数调优中讲解过这个参数。如果内存充足,而且很少使用持久化操作,建议调高这个比例,给shuffle read的聚合操作更多内存,以避免由于内存不足导致聚合过程中频繁读写磁盘。在实践中发现,合理调节该参数可以将性能提升10%左右。

spark.shuffle.manager

默认值:sort

参数说明:该参数用于设置ShuffleManager的类型。Spark 1.5以后,有三个可选项:hash、sort和tungsten-sort。HashShuffleManager是Spark 1.2以前的默认选项,但是Spark 1.2以及之后的版本默认都是SortShuffleManager了。tungsten-sort与sort类似,但是使用了tungsten计划中的堆外内存管理机制,内存使用效率更高。

调优建议:由于SortShuffleManager默认会对数据进行排序,因此如果你的业务逻辑中需要该排序机制的话,则使用默认的SortShuffleManager就可以;而如果你的业务逻辑不需要对数据进行排序,那么建议参考后面的几个参数调优,通过bypass机制或优化的HashShuffleManager来避免排序操作,同时提供较好的磁盘读写性能。这里要注意的是,tungsten-sort要慎用,因为之前发现了一些相应的bug。

spark.shuffle.sort.bypassMergeThreshold

默认值:200

参数说明:当ShuffleManager为SortShuffleManager时,如果shuffle read task的数量小于这个阈值(默认是200),则shuffle write过程中不会进行排序操作,而是直接按照未经优化的HashShuffleManager的方式去写数据,但是最后会将每个task产生的所有临时磁盘文件都合并成一个文件,并会创建单独的索引文件。

调优建议:当你使用SortShuffleManager时,如果的确不需要排序操作,那么建议将这个参数调大一些,大于shuffle read task的数量。那么此时就会自动启用bypass机制,map-side就不会进行排序了,减少了排序的性能开销。但是这种方式下,依然会产生大量的磁盘文件,因此shuffle write性能有待提高。

Spark.shuffle.io.maxRetries
默认值:3
参数说明:shuffle read任务从shuffle write任务那里节点正在拉自己的数据,如果网络由于异常拉失败而失败,它将自动重试。 此参数表示可以重试的最大次数。 如果在指定的次数内进行或不成功,则可能导致作业失败。

调优建议:
对于那些包含耗时的shuffle的作业,建议增加最大重试次数(例如60次),以避免由于诸如JVM或网络的完整gc之类的因素而导致数据失败。 不稳定。 在实践中发现,对于大量数据(数十亿到数十亿的shuffle过程),调整参数可以大大提高稳定性。
 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
SparkSQL可以采用以下几种优化技术来提高查询性能: 1. 数据分区(Partitioning):将数据分为多个分区,每个分区可以在不同的节点上进行处理,从而提高查询效率。可以使用repartition或coalesce方法进行数据分区。 2. 数据缓存(Caching):将经常使用的数据缓存到内存或磁盘中,可以避免重复计算,提高查询速度。可以使用cache或persist方法进行数据缓存。 3. 操作顺序(Operation Ordering):优化操作的顺序,将开销大的操作放在后面执行,减少计算的开销。可以使用explain方法查看执行计划,确定操作的执行顺序。 4. 数据过滤(Data Filtering):在查询过程中尽可能地进行数据过滤,减少需要处理的数据量。可以使用where或filter方法进行数据过滤。 5. 数据压缩(Data Compression):对数据进行压缩,可以减少数据的存储空间,提高数据的读取速度。可以使用compression参数进行数据压缩。 6. 数据分桶(Bucketing):将数据按照某个字段进行分桶,可以提高数据的查询效率。可以使用bucketBy方法进行数据分桶。 以下是一个SparkSQL优化的例子: ```python from pyspark.sql import SparkSession # 创建SparkSession spark = SparkSession.builder.appName("SparkSQL Optimization").getOrCreate() # 读取CSV文件 df = spark.read.csv("data.csv", header=True, inferSchema=True) # 数据分区 df = df.repartition(4) # 数据缓存 df.cache() # 操作顺序 df = df.select("col1", "col2", "col3").filter("col1 > 100").groupBy("col2").agg({"col3": "sum"}).orderBy("col2") # 数据过滤 df = df.filter("col2 > 50") # 显示结果 df.show() # 停止SparkSession spark.stop() ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值