Hive数据倾斜

  数据倾斜主要表现在MapReduce程序执行时,Reduce节点大部分执行完毕,但由于个别Reduce节点运行很慢,导致整个程序的处理时间很长。这是因为某一个Key的条数比其他Key多很多,导致这条Key所在的Reduce节点所处理的数据量比其他节点就大很多,从而导致某几个节点迟迟运行不完。

发生数据倾斜的Situation

数据倾斜可能会发生在group过程/join过程

join过程

大表和小表关联时

  一个上千万行的记录表和一个几千行表之间join关联时,容易发生数据倾斜。Hive中小表与大表join的优化策略——把重复关联键少的表放在join前面做关联可以提高join的效率
  Reduce在接收全部Map的输出后会有一个排序所有键值对并合并写入磁盘文件的操作。写入磁盘(spill)有可能是多次的,因此有可能会生成多个临时文件,但是最终都要合并成一个文件,即最终每一个Reduce都只处理一个文件。不论多复杂的Hive查询,最终都要转化成Mapreduce的job去执行,因此Hive对于关联的实现和Mapreduce对于关联的实现类似,即:把关联键和标记是在join左边还是右边的标识位作为组合键(key),把一条记录以及标记是在join左边还是右边的标识位组合起来作为值(value)。在Reduce的shuffle阶段,按照组合键的关联键进行主排序,当关联键相同时,再按照标识位进行辅助排序。而在分区段时,只用组合键中的关联键进行分区段,这样关联键相同的记录就会放在同一个value list中,同时保证了join左边的表的记录在value list的前面,而join右边的表的记录在value list的后面。
  对于A join B ON (A.id = b.id) ,假设A表和B表都有1条id =6的记录,那么A表这条记录的组合键是(6,0),B表这条记录的组合键是(6,1)。排序时可以保证A表的记录在B表的记录的前面。而在Reduce做处理时,把id=6的放在同一个value list中,形成 key = 6,value list = [A表id=6的记录,B表id=6的记录]。当两个表做关联时,Reduce会一起处理id相同的所有记录。把value list用数组来表示。
  1) Reduce先读取第一条记录v[0],如果发现v[0]是B表的记录,那说明没有A表的记录,最终不会关联输出,因此不用再继续处理这个id了,读取v[0]用了1次读取操作。如果发现v[0]到v[length-1]全部是A表的记录,那说明没有B表的记录,同样最终不会关联输出,但是这里注意,已经对value做了length次的读取操作。
  2) 例如A表id=6有1条记录,B表id=6有10条记录。首先读取v[0]发现是A表的记录,用了1次读取操作。然后再读取v[1]发现是B表的操作,这时v[0]和v[1]可以直接关联输出了,累计用了2次操作。这时候Reduce已经知道从v[1]开始后面都是B 表的记录了,因此可以直接用v[0]依次和v[2],v[3]……v[10]做关联操作并输出,累计用了11次操作。
  3) 换过来,假设A表id=6有10条记录,B表id=6有1条记录。首先读取v[0]发现是A表的记录,用了1次读取操作。然后再读取v[1]发现依然是A表的记录,累计用了2次读取操作。以此类推,读取v[9]时发现还是A表的记录,累计用了10次读取操作。然后读取最后1条记录v[10]发现是B表的记录,可以将v[0]和v[10]进行关联输出,累计用了11次操作。接下来可以直接把v[1]~v[9]分别与v[10]进行关联输出,累计用了20次操作。
  4) 当Reduce检测A表的记录时,还要记录A表同一个key的记录的条数,当发现同一个key的记录个数超过hive.skewjoin.key的值(默认为1000000)时,会在Reduce的日志中打印出该key,并标记为倾斜的关联键。
结论:写在关联左侧的表每有1条重复的关联键时底层就会多1次运算处理。假设A表有一千万个id,平均每个id有3条重复值,那么把A表放在前面做关联就会多做三千万次的运算处理。

解决方式
1.多表关联时,将小表(关联键记录少的表)依次放到前面,这样可以触发Reduce端更少的操作次数,减少运行时间。
2.同时可以使用Map Join让小的维度表缓存到内存。在Map端完成join过程,从而省略掉Redcue端的工作。但是使

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值