Hive-性能优化

一、效率低下的原因

1、数据倾斜
2、关联操作,job数太多
3、小文件太多,导致map性能差

数据倾斜是指,在数据量大的情况下,效率较低。比如count(distinct)是按group by 字段分组,按distinct字段排序,一般这种分布方式是很倾斜的。举个例子:比如男uv,女uv,像淘宝一天30亿的pv,如果按性别分组,分配2个reduce,每个reduce处理15亿数据。
有数据倾斜时进行负载均衡,set hive.groupby.skewindata,当选项设定为 true。 生成的查询计划有两 个 MapReduce 任务。在第一个 MapReduce 中,map 的输出结果集合会随机分布到 reduce 中, 每个 reduce 做部分聚合操作,并输出结果。这样处理的结果是,相同的 Group By Key 有可 能分发到不同的 reduce 中,从而达到负载均衡的目的;第二个 MapReduce 任务再根据预处 理的数据结果按照 Group By Key 分布到 reduce 中(这个过程可以保证相同的 Group By Key 分布到同一个 reduce 中),最后完成最终的聚合操作。

二、配置优化

1、数据裁剪,包括字段裁剪,分区裁剪,只查询需要的列和分区。

2、join 操作:
应该将条目少的表/子查询放在 Join 操作符的左边。 因为在 Reduce 阶段,位于 Join 操作符左边的表的内容会被加载进内存,载入条目较少的表 可以有效减少 OOM(out of memory)即内存溢出
如果 Join 的 key 相同,不管有多少个表,都会则会合并为一个 Map-Reduce

3、合理设置map大小
数据分割默认值是256M,假设input目录下有100个文件,大小都是10M以内,那么hadoop会分隔成100个块从而产生100个map数,map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。

set mapred.max.split.size=100000000;  
set mapred.min.split.size.per.node=100000000;
set mapred.min.split.size.per.rack=100000000;
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

确定合并文件块的大小,大于文件块大小128m的,按照128m来分隔,小于128m,大于100m的,按照100m来分隔,把那些小于100m的(包括小文件和分隔大文件剩下的),进行合并

调整reduce个数
set mapred.reduce.tasks=15;
如下情况,不管你有没有调整reduce个数的参数,任务中一直都只有一个reduce任务
没有group by的汇总
用了Order by
有笛卡尔积

4、设置并行执行job
set hive.exec.parallel=true;
set hive.exec.parallel.thread.number=16; //同一个sql允许最大并行度,默认为8。
比如:如下sql ,四个map设置参数以后可以并行处理

insert overwrite table a partition(pt='0')  
select c1,c2 where key='0'  
insert overwrite table a partition(pt='1')  
select c1,c2 where key='1'  
insert overwrite table a partition(pt='2')  
select c1,c2 where key='2'  
insert overwrite table a partition(pt='3')  

三、SQL优化

1、无效ID在关联时的数据倾斜问题
ID出现主键为 null 的情况,如果取其中key值关联,就会碰到数据倾斜的问题。原因是 Hive 中,主键为 null 值的项会被当做相同的 Key 而分配进同一个计算 Map。
处理方法: WHEN a.user_id IS NULL THEN CONCAT(‘dp_hive’,RAND()) ELSE a.user_id END =b.user_id;

2、不同数据类型关联产生的倾斜问题
如果关联表既有int类型又有string 类型,默认的Hash操作会按int型的id来进行分配,这样会导致所有string类型id的记录都分配到一个Reducer中。
把数据类型转换为统一的类型,再做关联
select * from users a join logs b on a.usr_id = cast(b.user_id as string)
3、GROUP BY替代COUNT(DISTINCT)达到优化效果
当数据量大的时候,用GROUP BY 替代COUNT(DISTINCT)解决数据倾斜问题,但是当数据量小的时候,反而效果不好。
统计每日IP

```
CREATE TABLE ip_2014_12_29 AS SELECT COUNT(DISTINCT ip) AS IP FROM logdfs WHERE logdate='2014_12_29';
```
由于引入了DISTINCT,因此在Map阶段无法利用combine对输出结果消重,必须将id作为Key输出,在Reduce阶段再对来自于不同Map Task、相同Key的结果进行消重,计入最终统计值。
我们看到作业运行时的Reduce Task个数为1,对于统计大数据量时,这会导致最终Map的全部输出由单个的ReduceTask处理。这唯一的Reduce Task需要Shuffle大量的数据,并且进行排序聚合等处理,这使得它成为整个作业的IO和运算瓶颈。
统计每日IP(改造)

```
CREATE TABLE ip_2014_12_29 AS SELECT COUNT(1) AS IP FROM (SELECT DISTINCT ip from logdfs WHERE logdate='2014_12_29') tmp;
```
我们利用Hive对嵌套语句的支持,将原来一个MapReduce作业转换为两个作业,在第一阶段选出全部的非重复id,在第二阶段再对这些已消重的id进行计数。这样在第一阶段我们可以通过增大Reduce的并发数,并发处理Map输出。在第二阶段,由于id已经消重,因此COUNT(*)操作在Map阶段不需要输出原id数据,只输出一个合并后的计数即可。

四、总结:

1. 不怕数据多,就怕数据倾斜。
2. 对jobs数比较多的作业运行效率相对比较低,比如即使有几百行的表,如果多次关联多次汇总,产生十几个jobs,没半小时是跑不完的。map reduce作业初始化的时间是比较长的。
3. 对sum,count来说,不存在数据倾斜问题。
4. 对count(distinct ),效率较低,数据量一多,准出问题,如果是多count(distinct )效率更低。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值