SparkSql 常用参数配置

SparkSql 常用参数配置:

1、常用持久化:

RDD层面:

​ 持久化cache:内存

​ MEMORY_ONLY_SER:序列化(启用sparkkryo序列化)有效降低内存占用,但耗费更多cpu性能序列化,而且还要注册需要序列化的类;

​ 以yarn集群为例,一般数据可靠性要求高,memory and disk,yarn资源充足memory 的java序列化即可,yarn资源不充足可以采用kryo序列化;

DFrame&DataSet持久化:

​ cache:默认Memory and Disk采用的序列化为特有编码器序列化,大大降低内存占用;

2、分区和参数控制

sparksql默认shuffle默认分区数200,参数spark.sql.shuffle.partitions,以hdfs为sink容易产生大量小文件;

解决方案:

  • 根据数据量及内存资源,使用coalesce或reparttion算子减少分区;
  • 合理利用cpu资源,一般情况设置分区=cpu核数 x executor数x 2~3 ,是资源满负载运行
  • 使用广播变量,在小表join大表时,将小表广播避免shuffle,广播阈值10m

3、广播join

spark.sql.autoBroadcastJoinThreshold=10MB,-1为关闭

api操作时,需要导入org.apache.spark.sql.functions才能使用广播算子

广播原则:

​ http广播:driver向所有executor广播,性能耗费严重。已弃用

​ 洪流广播:driver端产生广播表,其余executor主动拉取(拉取原则:最近原则)

4、数据倾斜

  1. 网上:提高并行度,将200->1000 并不能解决数据倾斜,原来的相同key还是会跑到同一个分区;
  2. 广播join,小表不做shuffle
  3. 打散大表,扩容小表,例如:小表采用:随机数+key=newkey,而后flatmap。大表:采用key+随机数;一般可以解决数据倾斜但是由于扩容也会加大计算时间。一般情况在task完成困难时,采用;

5、SmebJoin

​ 大表join大表,默认sortmergejoin,join时会先进行排序,导致排序时间长;

​ SmebJoin采用sort merge bucket分桶表排序,大表转换为小表,表联合时减少无关项扫描,主要排序时间也会分配在创建分桶表时;

​ 使用条件:

  1. 两表进行分桶,桶的个数必须相等;
  2. 两边进行join时,join列=排序列=分桶列
  3. 建表时只能使用saveas建表
  4. 不足之处,每个桶都会产生大量小文件

6、堆外内存使用

yarn容器资源:yarn.scheduler.maximum-allocation-mb

spark提交资源:

spark.executor.memoryOverhead,spark.executor.memory, spark.memory.offHeap.size

  1. spark.executor.memory: spark提交任务时指定的堆内内存。

  2. spark.executor.memoryOverhead:spark堆外内存参数,内存额外开销,默认开启,默认值为spark.executor.memory*0.1并且会与最小值384mb做对比,取最大值。这就是为什么spark on yarn任务堆内内存填写申请1个g,而实际去yarn申请的内存不是1个g的原因。

  3. spark.memory.offHeap.size:堆外内存参数,spark中默认关闭,需要将spark.memory.enable.offheap.enable参数设置为true

spark提交资源

spark堆外内存,不由jvm管理,而有操作系统管理,避免gc回收。

7、AQE

引入在spark3.0后。

Dynamically coalescing shuffle partitions 动态合并shuffle分区

shuffle是非常昂贵的操作,因为它需要进行网络传输移动数据,以便下游进行计算。

最好的分区取决于数据,但是每个查询的阶段之间的数据大小可能相差很大,这使得该数字难以调整:

(1)如果分区太少,则每个分区的数据量可能会很大,处理这些数据量非常大的分区,可能需要将数据溢写到磁盘(例如,排序和聚合),降低了查询。

(2)如果分区太多,则每个分区的数据量大小可能很小,读取大量小的网络数据块,这也会导致I/O效率低而降低了查询速度。拥有大量的task(一个分区一个task)也会给Spark任务计划程序带来更多负担

启用aqe可以合并小分区为大分区。

默认启用aqe

spark.sql.adaptive.coalescePartitions.initialPartitionNum初始分区数

spark.dynamicAllocation.shuffleTracking.enabled spark动态资源分配,可以动态申请资源

Dynamically switching join strategies动态调整join策略如广播

​ 需要设置spark.sql.adaptive.localShuffleReader.enabled=true 默认为true

​ 可以在运行中根据数据量大小进行是否广播。

Dynamically optimizing skew joins 动态解决数据倾斜

​ 1.spark.sql.adaptive.skewJoin.enabled :是否开启倾斜join检测,如果开启了,那么会将倾斜的分区数据拆成多个分区,默认是开启的,但是得打开ape。

​ 2.spark.sql.adaptive.skewJoin.skewedPartitionFactor :默认值5,此参数用来判断分区数据量是否数据倾斜,当任务中最大数据量分区对应的数据量大于的分区中位数乘以此参数(5),并且也大于spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes参数,那么任务此任务数据倾斜

​ 3.spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes :默认值256mb,用于判断是否数据倾斜

​ 4.spark.sql.adaptive.advisoryPartitionSizeInBytes :此参数用来告诉spark进行拆分后推荐分区大小是多少

8、Spark3.0DPP

动态分区裁剪[Dynamic Partition Pruning](#:~:text=Dynamic partition pruning occurs when,any number of dimension tables.),简称DPP。

核心思路就是先将join一侧作为子查询计算出来,再将其所有分区用到join另一侧作为表过滤条件,从而实现对分区的动态修剪

触发条件:

(1)待裁剪的表join的时候,join条件里必须有分区字段

(2)如果是需要修剪左表,那么join必须是inner join ,left semi join或right join,反之亦然。但如果是left out join,无论右边有没有这个分区,左边的值都存在,就不需要被裁剪

(3)另一张表需要存在至少一个过滤条件,比如a join b on a.key=b.key and a.id<2

9、spark3.0Hint增强

暗示,sort merge join,shuffle_hash join,shuffle_replicate nested loop join,broadcasthash join

你可能感兴趣的:(spark)