Hive优化 + 数据倾斜 +典型案例

优化

1、Fetch抓取

hive.fetch.task.conversion 设置成 more 执行一些limit,select 单个字段不会跑mr程序

2、本地模式

hive.exec.mode.local.auto 的值为 true

3、表的优化

3.1、老版本hive,把数据小的表放在join的左边,新版本已经优化了这个方法,放在join左边跟右边没有区别了,

3.2、空key过滤

select n.* from (select * from nullidtable where id is not null ) n   left join ori o on n.id = o.id;

空key转换,有时空值对应的数据不是错误数据,我们也需要处理,可以对这个key进行转换,使用随机值进行转换,使得随机到不同得reduce中

4、开启 Mapjoin 功能

 

set hive.auto.convert.join = true; 默认为 true

  1. 开启 Map 端聚合参数设置
    1. 是否在Map 端进行聚合,默认为 True hive.map.aggr = true
    2. 在 Map 端进行聚合操作的条目数目

 

hive.groupby.mapaggr.checkinterval = 100000

 

    1. 有数据倾斜的时候进行负载均衡(默认是 false) hive.groupby.skewindata = true

5、动态分区设置

set hive.exec.dynamici.partition=true;

set hive.exec.dynamic.partition.mode=nonstrict;

set hive.exec.mode.local.auto=true;

SET hive.exec.max.dynamic.partitions=100000;

SET hive.exec.max.dynamic.partitions.pernode=100000;

set hive.exec.max.created.files=100000;

6、当然了,还有我们得分区分桶概念

 

 

数据倾斜

 

1、合并小文件

set hive.input.format= org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

2、复杂文件增加Map数量

如果map执行的非常慢的话,可以考虑增加map得数量

computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M 公式,调整 maxSize 最大值。让 maxSize 最大值低于 blocksize 就可以增加 map 的个数。

set mapreduce.input.fileinputformat.split.maxsize=100(设置最大切片值为 100m)

3、JVM重用

4、严格模式

5、推测执行

6、压缩

典型的业务场景

1、空值产生的数据倾斜

场景:如日志中,常会有信息丢失的问题,比如日志中的 user_id,如果取其中的 user_id 和 用户表中的user_id 关联,会碰到数据倾斜的问题。

解决方法1: user_id为空的不参与关联(红色字体为修改后)

select * from log a  join users b  on a.user_id is not null  and a.user_id = b.user_idunion allselect * from log a  where a.user_id is null;

解决方法2 :赋与空值分新的key值

select *  from log a  left outer join users b  on case when a.user_id is null then concat(‘hive’,rand() ) else a.user_id end = b.user_id;

结论:方法2比方法1效率更好,不但io少了,而且作业数也少了。解决方法1中 log读取两次,jobs是2。解决方法2 job数是1 。这个优化适合无效 id (比如 -99 , ’’, null 等) 产生的倾斜问题。把空值的 key 变成一个字符串加上随机数,就能把倾斜的数据分到不同的reduce上 ,解决数据倾斜问题。

2、不同数据类型关联产生数据倾斜

场景:用户表中user_id字段为int,log表中user_id字段既有string类型也有int类型。当按照user_id进行两个表的Join操作时,默认的Hash操作会按int型的id来进行分配,这样会导致所有string类型id的记录都分配到一个Reducer中。

解决方法:把数字类型转换成字符串类型

select * from users a  left outer join logs b  on a.usr_id = cast(b.user_id as string)

3、将小表进行map的聚合,再map端放入内存,以供使用(reduce join转换为map join)

总结

使map的输出数据更均匀的分布到reduce中去,是我们的最终目标。由于Hash算法的局限性,按key Hash会或多或少的造成数据倾斜。大量经验表明数据倾斜的原因是人为的建表疏忽或业务逻辑可以规避的。在此给出较为通用的步骤:

1、采样log表,哪些user_id比较倾斜,得到一个结果表tmp1。由于对计算框架来说,所有的数据过来,他都是不知道数据分布情况的,所以采样是并不可少的。

2、数据的分布符合社会学统计规则,贫富不均。倾斜的key不会太多,就像一个社会的富人不多,奇特的人不多一样。所以tmp1记录数会很少。把tmp1和users做map join生成tmp2,把tmp2读到distribute file cache。这是一个map过程。

3、map读入users和log,假如记录来自log,则检查user_id是否在tmp2里,如果是,输出到本地文件a,否则生成的key,value对,假如记录来自member,生成的key,value对,进入reduce阶段。

4、最终把a文件,把Stage3 reduce阶段输出的文件合并起写到hdfs。

 

如果确认业务需要这样倾斜的逻辑,考虑以下的优化方案:

1、对于join,在判断小表不大于1G的情况下,使用map join

2、对于group by或distinct,设定 hive.groupby.skewindata=true

3、尽量使用上述的SQL语句调节进行优化

 

 

 

 

 

 

 

你可能感兴趣的:(Hive优化 + 数据倾斜 +典型案例)