开发性能调优之数据倾斜调优
一、数据倾斜原因
常见表现:在hive中 map阶段早就跑完了,reduce阶段一直卡在99%。很大情况是发生了数据倾斜,整个任务在等某个节点跑完。 在spark中大部分的task执行的特别快,剩下的一些task执行的特别慢,要几分钟或几十分钟才执行完一个task Hive中大表join的时候,容易产生数据倾斜问题,spark中产生shuffle类算子的操作,groupbykey、reducebykey、join等操作会引起数据倾斜。通过stage去定位
数据倾斜原因: 在进行shuffle的时候,必须将各个节点上相同的key拉取到某个节点上的一个task来进行处理,比如按照key进行聚合或join等操作。此时如果某个key对应的数据量特别大的话,就会发生数据倾斜。比如大部分key对应10条数据,但是个别key却对应了100万条数据,那么大部分task可能就只会分配到10条数据,然后1秒钟就运行完了;但是个别task可能分配到了100万数据,要运行一两个小时
二、方案
解决方法1:直接过滤掉那些引起倾斜的key
比如说,总共有100万个key。只有2 个key,是数据量达到10 万的。其他所有的key,对应的数量都是几十,这样join后会引起倾斜。这个时候,自己可以去取舍,如果业务和需求可以理解和接受的话,在从hive 表查询源数据的时候,直接在sql 中用where 条件,过滤掉某几个key。那么这几个原先有大量数据,会导致数据倾斜的key,被过滤掉之后,那么在的spark作业中,自然就不会发生数据倾斜了。
解决方法2:Hive ETL做处理
导致数据倾斜的是Hive表。如果该Hive表中的数据本身很不均匀(比如某个key对应了100万数据,其他key才对应了10条数据),而且应用中需要频繁使用Spark对Hive表执行分析操作时,可以使用Hive ETL去做一个预处理 实现方式 通过Hive ETL预先对数据按照key进行聚合,或者是预先和其他表进行join,然后在Spark作业中针对的数据源就不是原来的Hive表了,而是预处理后的Hive表。此时由于数据已经预先进行过聚合或join操作了,那么在Spark作业中也就不需要使用原先的shuffle类算子执行这类操作了。Hive ETL中进行group by或者join等shuffle操作时,还是会出现数据倾斜,导致Hive ETL的速度很慢。我们只是把数据倾斜的发生提前到了Hive ETL中
解决方法3:提高shuffle操作并行度
在对RDD执行shuffle算子时,给shuffle算子传入一个参数,比如reduceByKey(1000),该参数就设置了这个shuffle算子执行时shuffle read task的数量。对于Spark SQL中的shuffle类语句,比如group by、join等,需要设置一个参数,即spark.sql.shuffle.partitions,该参数代表了shuffle read task的并行度,该值默认是200,对于很多场景来说都有点过小
原理:增加shuffle read task的数量,可以让原本分配给一个task的多个key分配给多个task,从而让每个task处理比原来更少的数据。举例来说,如果原本有5个key,每个key对应10条数据,这5个key都是分配给一个task的,那么这个task就要处理50条数据。而增加了shuffle read task以后,每个task就分配到一个key,即每个task就处理10条数据,那么自然每个task的执行时间都会变短了