在日常的etl开发的过程中,不管是使用spark,或者是hive来做开发,经常会遇见任务跑的特别慢,或者任务出现oom,或者数据量并不大,但是任务就是跑的特别慢等等情况。
关于任务的优化,我将自己工作中用到的一些小的trick分享出来。
数据倾斜
数据倾斜是什么?数据倾斜是在计算数据的时候,数据的分散度不够,大量的数据集中在一台或者几台机器上计算,导致整个计算过程过慢甚至失败。
举个例子,1TB的数据,十台机器并行计算,由于数据分区不合理,9台机器上各承担了10GB的计算任务,剩下910GB的数据在一台机器上。因而负载大的机器,需要的资源过大,运行的时间过长等等问题。
数据倾斜的表现
- hadoop中的数据倾斜
- 一个或者多个reduce卡主
- 各种oom报错
*单个reduce, 读写的数据量极大
- spark中的数据倾斜
- Excutor lost, OOM, shuffle过程出错
- Driver OOM
- 单个Executor执行特别就,整个任务卡在某个阶段不能执行
- 正常运行的任务突然失败
问题查找
- hadoop中的问题查找
- 读取的数据源是否数据倾斜
- group或者on的时候,是否有大量相同的key
- spark中的问题查找
- 读取的数据源是否数据倾斜
- spark计算中的数据倾斜,只可能发生在shuffle操作阶段。查找代码,啊中的程序
- 读取数据源,按照猜测对某几个字段进行group统计,定位倾斜的字段
- 看log,根据spark ui,确定是哪个stage特别慢。然后根据stage,定位代码
问题解决
这个问题的解决主要从三个方面进行着手解决:业务逻辑、程序层面和调参方面
业务逻辑
-
如果读取的数据源倾斜比较严重,则上游写入数据平均一些
-
将直接聚合,改为二级甚至三级聚合。比如:
select key1, xxx from a group by key1.
改为
select key1, xxx from ( select key1, key2, key3, xxx from a group by key1, key2, key3) group by key1 -
与2类似,如果没有存在的字段用于多重聚合。可以生成随机key,实现多重聚合。
-
区别对待,将倾斜的key的数据单独处理。比如倾斜的key,增加并行度等等方式。这里如何判断倾斜的key,可以使用历史数据或者随机sample的方式判断。或者倾斜的key单独join或者group不要等操作
-
自定义分区,需要用户自定义实现分区策略,这种方法效果比较明显。
程序层面
- 使用group by 提到count(dinstinc xxx)操作
调仓方面
- 不管是hive还是spark,如果有小表与大表join,可以使用mapjoin提到reduce join
- hsql,可以调整map, reduce的个数,来缓解数据倾斜问题
- 更多相关参数,可以去官网撸一遍配置
拆数据
另外一个关于任务优化的办法,就是化大为小,将大任务拆成小任务。下面提供几个拆数据的思路。
- 时间维度,将天任务改成小时任务,甚至将小时任务改成分钟任务甚至秒级别的实时任务。这样单次处理的任务数据量会小很多,比较好处理。
- 按照某个维度,对数据进行拆分,使用多个任务进行并行处理
合数据
天下合久必分,分久必合。如果一旦数据拆分特别细,导致hive分区过多,则会出现任务特别慢的情况。这种情况,可能就要考虑合并文件
预计算
这个思路是将可以提前计算的数据提前计算好,一旦等待的数据ready之后,可以更快的计算处理。
举个例子,原本一个任务需要读取A和B两份数据,A数据第二天凌晨1点就好了,B数据需要到第二天10点才能ready。如果在B数据好了之后再开始数据,则任务需要运行1个小时。但是通过修改代码,可以将A数据提前计算好,等到B数据ready之后,再进行计算,只需要20分钟。业务就可以看到数据了。
其他零零散散的任务优化技巧
- 大量的spark小任务,可以使用多线程提升效率
- 当涉及到大量数据任务的数据流的时候,优化数据产出流程或者重新建模,可能会更快的产出最终的数据。
参考资料
- https://blog.youkuaiyun.com/u010039929/article/details/55044407
- https://zhuanlan.zhihu.com/p/64240857