Hive数仓

Hive5:Hive优化

2020-04-29  本文已影响0人  勇于自信

Map优化

  1. 通过调整脚本的参数来设置map的个数,和设置block大小,block是影响map个数的关键因素

直接设置map个数:set mapred.map.tasks=10

 2.为了任务加快,有一些任务可以考虑开启compiners:

  Hive.map.aggr=true

Reduce优化:

1.提交sql,设置的参数

原因:有一个reduce个数的计算公式,这个公式依赖于这个参数

Reduce个数=InputFileSize(整个文件数据的大小)/bytes per reducer(每一个reduce处理的大小)

这个参数就是设置分母

2.直接设置reduce的个数:

In order to change the average load for a reducer (in bytes):
set hive.exec.reducers.bytes.per.reducer=<number>
如果大于<number>,就会多生成一个reduce
<number> =1024 <1k 一个reduce
1m 10个reduce

set hive.exec.reducers.bytes.per.reducer=20000;
select user_id,count(1) as order_cnt
from orders group by user_id limit 10;
--结果number of mappers: 1; number of reducers: 1009

In order to limit the maximum number of reducers:
set hive.exec.reducers.max=<number>
set hive.exec.reducers.max=10;
-- number of mappers: 1; number of reducers: 10

In order to set a constant number of reducers:
set mapreduce.job.reduces=<number>
set mapreduce.job.reduces=5;
--number of mappers: 1; number of reducers: 5
set mapreduce.job.reduces=15;
--number of mappers: 1; number of reducers: 15
对你当前窗口,或者执行任务(脚本)过程中生效

3.对于没有group by,又做了count这样聚合的函数的时候它最后跑出来的reduce个数就是一个

4.分区优化:

​减少不必要的数据过滤。

5.笛卡尔积优化:

用where取代on

6.map join优化:

Map join:类似一种检索配置文件的形式

例如:A是一个文件,B是一个文件,A.join B

如果A是小表,考虑是否可以将A放入内存,只遍历大表B,大表可以帮忙做一个性能的提升。

如何知道哪个是小表和大表:

MAPJOIN(tablelist)明确mapjoin里是小表

/*+ STREAMTABLE(a) */ a是大表

类似map join 放到select中的,区别:它是指定大表
select /+STREAMTABLE(pr)/ ord.order_id,pr.product_id,pro.aisle_id
from orders ord
join priors pr on ord.order_id=pr.order_id
join products pro on pr.product_id=pro.product_id
limit 10;

7.union/union all优化:

union all / distinct == union
--运行时间:74.712 seconds 2job
select count(distinct *)
from (
select order_id,user_id,order_dow from orders where order_dow='0' union all
select order_id,user_id,order_dow from orders where order_dow='0' union all
select order_id,user_id,order_dow from orders where order_dow='1'
)t;

--运行时间122.996 seconds 3 job
select count(*)
from(
select order_id,user_id,order_dow from orders where order_dow='0' union
select order_id,user_id,order_dow from orders where order_dow='0' union
select order_id,user_id,order_dow from orders where order_dow='1')t;

8.两个不同任务来自一张表的优化:

从公共表取数据写到另外一张表里,例如:

9.执行hive任务的时候会产生一些临时中间文件,中间小的文件比较多,如何对多个小文件进行合并:

配置参数:map阶段,reduce结果做合并,每个任务预期合并的size大小

10.数据倾斜问题优化:

假设数据源存在数据倾斜问题(有的key的记录多,有的key的记录少,记录多的跑到同一个

Reduce里,会导致一个reduce特别慢,key的分布不均匀)

优化方法:

10.1.Mr:对key做改写来解决类似问题

10.2.Hive:hive.groupby.skewindata这个参数会帮你完成一定的负载均衡

如果在不导致reduce一直失败起不来的时候,就不用这个变量
如果确实出现了其中一个reduce的处理数据量太多,导致任务一直出问题,运行时间长。这种情况需要设置这个变量。

10.3 '-' ,where age<>'-' 直接丢掉这个数据
select age,count(1) group by age where age<>'-'

怎么定位具体哪几个key发生倾斜?
sample(简单采样)

10.4 空间换时间

案例: Select day,count(distinct session_id),count(distinct user_id) from log a group by day
问题:
同一个reduce上进行distinct操作时压力很大
方法:
select day,
count(case when type='session' then 1 else null end) as session_cnt, • count(case when type='user' then 1 else null end) as user_cnt
from (
select day,session_id,type
from (
select day,session_id,'session' as type
from log
union all
select day user_id,'user' as type
from log
) • group by day,session_id,type
) t1
group by day

11.sql语句优化

例如如下两个sql语句:

第一条sql语句在join后再进行过滤,相当于做了两步。

第二条sql语句在join过程中就对条件进行了预先过滤。

12.并行执行MapReduce优化,如下图:

例如每个圆形就是一个MapReduce,橙色部分需要依赖别人,蓝色部分没有相互依赖关系的节点就可以尽可能地单独执行。

那么蓝色的MapReduce就可以同时执行,就是并行。设置并行执行的方法:

开启并行的方法:Set hive.exec.parallel设置为true

同步执行hive的多个阶段,hive在执行过程,将一个查询转化成一个或者多个阶段。某个特
定的job可能包含众多的阶段,而这些阶段可能并非完全相互依赖的,也就是说可以并行执行
的,这样可能使得整个job的执行时间缩短。
hive执行开启:
set hive.exec.parallel=true

13.大小表关联的优化:
原理:
Hive在进行join时,按照join的key进行分发,而在join左边的表的数据会首先读入内存,如果左边表的key相对
分散,读入内存的数据会比较小,join任务执行会比较快;而如果左边的表key比较集中,而这张表的数据量很大,那么数据倾斜就会比较严重,而如果这张表是小表,则还是应该把这张表放在join左边。

优化思路:
将key相对分散,并且数据量小的表放在join的左边,这样可以有效减少内存溢出错误发生的几率
使用map join让小的维度表先进内存。
方法:
Small_table join big_table

14.分组的特殊值处理优化:
原理:例如日志中有一部分的userid是空或者是0的情况,导致在用user_id进行hash分桶的时候,会将日志中userid为0或者空的数据分到一起,导致了过大的斜率。
优化思路:
把空值的key变成一个字符串加上随机数,把倾斜的数据分到不同的reduce上,由于null值关联不上,处理后并不影响最终结果。
方法:
on case when (x.uid = '-' or x.uid = '0‘ or x.uid is null) then concat('dp_hive_search',rand()) else x.uid
end = f.user_id;

  1. 大大表关联的优化:
    案例:Select * from dw_log t join dw_user t1 on t.user_id=t1.user_id
    现象:两个表都上千万,跑起来很悬

思路:
当天登陆的用户其实很少,将绝大部分没用的用户的基础信息过滤掉,结合业务的特点,将大表变成小表
方法:
Select/+MAPJOIN(t12)/ *
from dw_log t11
join (
select/+MAPJOIN(t)/ t1.*
from (
select user_id from dw_log group by user_id
) t
join dw_user t1
on t.user_id=t1.user_id
) t12
on t11.user_id=t12.user_id

  1. 聚合时存在大量特殊值的优化
    原因:
    做count distinct时,该字段存在大量值为NULL或空的记录。
    思路:
    count distinct时,将值为空的情况单独处理,如果是计算count distinct,可以不用处理,直接过滤,在最后结果中加1。如果还有其他计算,需要进行group by,可以先将值为空的记录单独处理,再和其他计算结果进行union
    方法:
    select cast(count(distinct(user_id))+1 as bigint) as user_cnt
    • from tab_a
    • where user_id is not null and user_id <> ''
上一篇下一篇

猜你喜欢

热点阅读