NightPxy 个人技术博客

Hive 数据倾斜

Posted on By NightPxy

##

发生数据倾斜的第一要务是找出倾斜键,这时分析和处理的前提

发现

出现某个或某小部分的ReduceTask严重滞后于其它任务执行,超时关闭甚至出现OOM错误,就需要警惕是否存在数据倾斜
注意

  • 数据倾斜一般是倾斜在极小部分的任务中,如果出现基本所有的任务都卡住且彼此处理差距不大,就不应该是数据倾斜而是任务数设少了,并行度太低
  • 还有一种特殊情况是某个执行节点本身有问题导致任务慢,杀死切换一个节点

如果判定有可能是数据倾斜
YARN-UI Counter会记录整个job以及每个task的统计信息
如果是数据倾斜,通过输入记录数和输出字符数应该可以看出是其它任务大N倍

定位倾斜

定位倾斜的可以查看执行慢的任务的Hive日志,看看任务长期卡在哪一个Stage,然后配合查看语句的执行计划,反向推出哪段语句出现了倾斜
通过分析卡住的SQL,就能知道是什么表做什么操作的时候卡住了
之后就可以通过工具,HUE之类的,对这个表统计下操作列分布或者取样,就可以定位出倾斜列的倾斜键是什么

解决方案

是否允许过滤倾斜键

有很大部分的倾斜键是出现在脏数据或者废数据中,比如Null,或者业务Null(-1,-99)等等,此时就可以过滤掉倾斜键,不会出现倾斜键,也就不会出现数据倾斜了

分治倾斜键

首先,将数据整体分为正常部分和倾斜部分分别处理,正常部分没有倾斜,所以是可以很流畅的处理
倾斜部分,为倾斜键打上指定范围内的随机前缀,这样对处理强行分割为多个任务处理,之后再对倾斜键分割出的多个任务执行结果再重新聚合为整个倾斜部分结果
倾斜部分成功处理后,再合并倾斜部分和正常,就是最终结果了
基本所有的倾斜问题都可以用分治倾斜键来解决,但同时也是最麻烦的

groupBy倾斜

groupBy一般是为了聚合,可以考虑单提倾斜键单独计算聚合最后再Union回去

还有groupBy一定要注意必须尽量靠起Combiner(执行计划),必要时写子查询 比如 count distinct,就是 GroupBy分组,再对distinct列排序,然后全部输出交给Reduce,这时应写子查询先distinct,这样可以 Combiner distinct 再参与 groupBy Count

也可以分治倾斜键,Hive对GroupBy分治倾斜,提供了自动实现
hive.map.aggr=true Map端聚合,相当于Combiner
hive.groupby.skewindata=true
注意,使用自动分治倾斜的前提是,倾斜必须体现在元数据中.因为自动分治倾斜的判定依据是元数据,否则开启自动分治也没有任何效果

join键倾斜

join键倾斜的倾斜,还有一些特殊的技巧

如果大小表,小是指小于22M,Hive配置,可以使用Map-Join,将小表再Map阶段加入内存,一次遍历中通过Hash匹配就直接完成,都没有倾斜的机会.Hive中配置,检测到小表就可以自动转换为MapJoin

如果是大表关联,有三个思路

  • 强行构造出小表,走MapJoin
    大致思路是,根据查询列,连接键等,对其中一张相对较小的表强行去重为一种中间表,然后再进行MapJoin
    这种思路是要求 连接的某一张表虽然数据量很大,但重复率很高,要求去重后的中间表必须满足Mapjoin的要求,对数据要求最高但是效果最好
  • 分治倾斜键
    Hive 开启 hive.optimize.skewjoin. 将会为连接倾斜键自动创建多个Job,大致也是分治原理
    但是,这种自动的倾斜处理,是依赖元数据中的倾斜信息来判定的,即倾斜信息必须正确的被存储在元数据中,否则不会有任何效果
    这种适合是倾斜问题,即少部分的键数据很多
  • Sort-Merg-Join
    如果就是单纯的大,即不是少部分的键数据很多,而是很多的键数据都很多,就可以考虑Sort-Merg-Join