1、内存优化

1.1、RDD

RDD默认cache仅使用内存

sparksql orderBy sparksql orderby优化_缓存

sparksql orderBy sparksql orderby优化_spark_02

可以看到使用默认cache时,四个分区只在内存中缓存了3个分区,4.4G的数据

sparksql orderBy sparksql orderby优化_sparksql orderBy_03

使用kryo序列化+MEMORY_ONLY_SER

sparksql orderBy sparksql orderby优化_spark_04

 

sparksql orderBy sparksql orderby优化_sql_05

可以看到缓存了四个分区的全部数据,且只缓存了1445.8M

sparksql orderBy sparksql orderby优化_sql_06

所以这两种缓存方式如何选择,官网建议

sparksql orderBy sparksql orderby优化_缓存_07

也就是说集群资源足够使用默认cache,资源紧张使用kryo序列化+MEMORY_ONLY_SER

1.2、DataFrame与DataSet

DataSet不使用Java和Kryo序列化,它使用特殊的编码器序列化

sparksql orderBy sparksql orderby优化_sparksql orderBy_08

使用默认cache,保存在内存和磁盘

sparksql orderBy sparksql orderby优化_spark_09

sparksql orderBy sparksql orderby优化_spark_10

同样多的数据也是全部缓存,只使用了内存612.3M

 

sparksql orderBy sparksql orderby优化_spark_11

使用序列化缓存时比使用默认缓存还多缓存了30M,共646.2M

sparksql orderBy sparksql orderby优化_spark_12

sparksql orderBy sparksql orderby优化_缓存_13

df和ds直接使用默认cache即可

2、小文件过多问题

2.1、RDD中并行度设置

spark.default.parallelism

For distributed shuffle operations like reduceByKey and join, the largest number of partitions in a parent RDD. For operations like parallelize with no parent RDDs, it depends on the cluster manager:
Local mode: number of cores on the local machine
Mesos fine grained mode: 8
Others: total number of cores on all executor nodes or 2, whichever is larger
Default number of partitions in RDDs returned by transformations like join, reduceByKey, and parallelize when not set by user.

2.2、spark sql

Spark SQL can cache tables using an in-memory columnar format by calling sqlContext.cacheTable("tableName") or dataFrame.cache(). Then Spark SQL will scan only required columns and will automatically tune compression to minimize memory usage and GC pressure. You can call sqlContext.uncacheTable("tableName") to remove the table from memory.
建议如果下面无其它任务,缓存可以不释放,有其它任务要释放
算子方式
result.unpersist

spark.sql.shuffle.partitions  Configures the number of partitions to use when shuffling data for joins or aggregations.

默认200 
如不减少分区,join后hadoop上会有200个小文件

sparksql orderBy sparksql orderby优化_spark_14

sparksql orderBy sparksql orderby优化_sparksql orderBy_15

sparksql orderBy sparksql orderby优化_sparksql orderBy_16

前三个stage为读文件(控制不了),后两个stage为join并行度,为200
1、使用coalesce算子缩小分区,不能大于原有分区数值
2、如果数值小于vcore,有些vcore就不会工作,速度会慢
如压缩成1,并行度就是1只有一个vcore在工作,不会shuffle,如果数据量很大且参数很小,可能会产生oom

sparksql orderBy sparksql orderby优化_sparksql orderBy_17

sparksql orderBy sparksql orderby优化_sparksql orderBy_18

sparksql orderBy sparksql orderby优化_sql_19

可以看到将分区减少到20,hadoop上只有20个文件

3、合理利用cpu资源

sparksql orderBy sparksql orderby优化_spark_20

sparksql orderBy sparksql orderby优化_spark_21

未优化时任务可以看到最后200个任务没有平均分到每台机器上,压力全在hadoop103上,如果数据量很少,hadoop103上有些vcore可能没数据在空转,没有合理利用cpu资源

将·spark.sql.shuffle.partitions设置为总vcore的2到3倍可以达到最优效果

sparksql orderBy sparksql orderby优化_sparksql orderBy_22

sparksql orderBy sparksql orderby优化_缓存_23

sparksql orderBy sparksql orderby优化_spark_24

sparksql orderBy sparksql orderby优化_缓存_25

不添加缩小分区coalesce可以看到有36个任务
任务分配也很平均,达到优化效果,避免空转情况,合理利用cpu资源,任务时间缩短到2.5分钟

4、广播join

将小表聚合到driver端,分发到每个executor,规避shuffle,避免此stage
只适合小表join大表

正常大表join大表走SortMergeJoin

 

sparksql orderBy sparksql orderby优化_缓存_26

小于等于10M,自动进行广播join
spark.sql.autoBroadcastJoinThreshold 

Configures the maximum size in bytes for a table that will be broadcast to all worker nodes when performing a join. By setting this value to -1 broadcasting can be disabled. Note that currently statistics are only supported for Hive Metastore tables where the command ANALYZE TABLE <tableName> COMPUTE STATISTICS noscan has been run.

4.1 API

禁用掉广播join ,设置参数为-1

sparksql orderBy sparksql orderby优化_sparksql orderBy_27

可以看到只剩下一个36task的join stage,多出来一步broadcast exchange,
变成BroadcastHashJoin 耗时变成2分钟

sparksql orderBy sparksql orderby优化_sql_28

sparksql orderBy sparksql orderby优化_sql_29

4.2 参数

单位不能是M,10485760

默认10M,实际生产可调大参数,如改成20MB,可以避免小表join大表时数据倾斜
set("spark.sql.autoBroadcastJoinThreshold","20971520")

sparksql orderBy sparksql orderby优化_spark_30

5、数据倾斜

sparksql orderBy sparksql orderby优化_sql_31

sparksql orderBy sparksql orderby优化_sql_32

并不只是500万,因为一个分区里不只一个key,包含多个key,如分区1 101 102 分区2 103 104
本质将相同key的数据聚集到一个task

sparksql orderBy sparksql orderby优化_缓存_33

5.1 解决数据倾斜错误方法

sparksql orderBy sparksql orderby优化_缓存_34

sparksql orderBy sparksql orderby优化_sql_35

sparksql orderBy sparksql orderby优化_缓存_36

5.2 解决数据倾斜

1、广播join

2、打散大表,扩容小表   能解决,但可能更加耗时,因为小表数据量增加了

除非情况非常严重,结果出不来

sparksql orderBy sparksql orderby优化_缓存_37

 

sparksql orderBy sparksql orderby优化_sparksql orderBy_38

 

拿打散后的courseId进行join

sparksql orderBy sparksql orderby优化_缓存_39

可以看到dataframe.map后变成dataset

sparksql orderBy sparksql orderby优化_spark_40

sparksql orderBy sparksql orderby优化_缓存_41

sparksql orderBy sparksql orderby优化_sql_42

循环里面为i+"_"+courseid,写错了

 

可以看到已经得到优化

sparksql orderBy sparksql orderby优化_sparksql orderBy_43

但是时间由变成50秒

sparksql orderBy sparksql orderby优化_sql_44

和3中只缩小分区34秒时间增加,虽然3中有数据倾斜

sparksql orderBy sparksql orderby优化_spark_45

sparksql orderBy sparksql orderby优化_缓存_46

6、SMB join

排序时间优化,数据量大的时候效果很明显

sparksql orderBy sparksql orderby优化_sparksql orderBy_47

sparksql orderBy sparksql orderby优化_sparksql orderBy_48

sparksql orderBy sparksql orderby优化_sparksql orderBy_49

spark中支持分桶必须用saveastable,insertinto不支持分桶

sparksql orderBy sparksql orderby优化_缓存_50

sparksql orderBy sparksql orderby优化_spark_51

先拿两张分桶表做join
分桶后task数就和分桶数一样

sparksql orderBy sparksql orderby优化_sparksql orderBy_52

 

sparksql orderBy sparksql orderby优化_spark_53

7、使用堆外内存

sparksql orderBy sparksql orderby优化_spark_54

sparksql orderBy sparksql orderby优化_spark_55

sparksql orderBy sparksql orderby优化_sparksql orderBy_56

3.0之前

sparksql orderBy sparksql orderby优化_spark_57

3.0之后

sparksql orderBy sparksql orderby优化_sparksql orderBy_58

修改内存测试

sparksql orderBy sparksql orderby优化_spark_59

max(2G*0.1 384)
2G+2G+384>4G
实际申请4个G,申请会大于4个G

sparksql orderBy sparksql orderby优化_sparksql orderBy_60

堆外内存使用

sparksql orderBy sparksql orderby优化_sparksql orderBy_61

sparksql orderBy sparksql orderby优化_spark_62

sparksql orderBy sparksql orderby优化_sparksql orderBy_63

sparksql orderBy sparksql orderby优化_sparksql orderBy_64

堆内堆外会互相借用

 

什么情况下使用堆外内存

sparksql orderBy sparksql orderby优化_spark_65