问题

如下读取mysql表时默认是一个分区 查询结果只有一个task在跑

1
val jdbcDF = spark.read.jdbc(url,tableName,prop)

这种读取读大表(千万级)就会OOM
因此在读取时要用到spark分区

理解spark分区

就是将一个非常大的任务拆分为多个小任务,小任务数量最好满足整除Executor数量*Executor核心数量,这样可以提供资源利用率。
这就是在spark调优中,增大RDD分区数目,增大任务并行度的原因。

spark分区 什么时候增加的,增加有什么用?

接下来的描述,是针对于sparksql(也就是把数据加载成Dataset之后再处理)来说的。

1.增加分区数,可以增加并行度,当spark申请的cpu核心足够的情况下,可以同时跑不同分区的数据(因为一个分区的数据,只能由一个核心来跑,不能多个)

2.手动增加,使用repartition来将所有数据打散

3.自动增加,spark有个参数:spark.sql.shuffle.partitions,默认值为200。也就是说当触发shuffle逻辑的时候,数据会自动分为200个分区运行,但是在数据量大的情况下,每个分区的数据量太大,而且假设spark申请到了300个核心,但是因为分区数只有200,会导致只有200个核心在运行,另外100个核心在空转(虽然占用资源但是却不干活)。所以可以将该参数设置为500甚至更大,来增加分区数和并行度。

repartition适用场景

RDD单个分区数据量比较大,或者单个分区处理比较慢,
数据倾斜

转载于
[https://blog.csdn.net/qq_22473611/article/details/107822168]