hive的优化

hive的优化

1.数据量较大的情况下慎用count(distinct name)

问题:使用disticnt函数,所有的数据只会shuffle到一个reducer上,导致reducer数据倾斜严重易造成数据倾斜,
比如:男UV,女UV,淘宝一天30亿的PV,如果按性别分组,分配2个reduce,每个reduce处理15亿数据。
优化:建议使用group by 字段,分组之后再对该字段做次数统计;
hive去重有几种方法?distinct 、 group by

2.order by全局排序 & sort by “局部有序”(分区内部排序)
  • (1).order by 会对输入做全局排序,因此只有一个reducer(多个reducer无法保证全局有序)
    只有一个reducer,会导致当数据输入规模较大时,需要较长的计算时间,影响效率.
    如果指定了hive.mapred.mode=strict(默认值是nonstrict),这时就必须指定limit来限制输出条数,
    原因是:所有的数据都会在同一个reducer端进行,数据量大的情况下可能不能出结果,那么在这样的严格模式下,必须指定输出的条数。
  • (2).如果用sort by进行排序,并且设置mapred.reduce.tasks>1, 则sort by只保证每个reducer的输出有序,不保证全局有序。
    每个reducer出来的数据是有序的,但是不能保证所有的数据是有序的,除非只有一个reducer
    好处是:执行了局部排序之后可以为接下去的全局排序提高不少的效率(其实就是做一次归并排序就可以做到全局排序了)
3.减少job数

原因:jobs数比较多的作业运行效率相对比较低,原因是map reduce作业初始化的时间是比较长的。
比如即使有几百行的表,如果多次关联多次汇总,产生十几个jobs,耗时很长。
***sum,count,max,min等UDAF,不怕数据倾斜问题,hadoop在map端的汇总合并优化,使数据倾斜不成问题

4.合并小文件

对小文件进行合并,是行至有效的提高调度效率的方法。
我们知道文件数目小,容易在文件存储端造成瓶颈,给 HDFS 带来压力,影响处理效率。
对此,可以通过合并Map和Reduce的结果文件来消除这样的影响。
用于设置合并属性的参数有:
是否合并Map输出文件:hive.merge.mapfiles=true(默认值为真)
是否合并Reduce端输出文件:hive.merge.mapredfiles=false(默认值为假)
合并文件的大小:hive.merge.size.per.task=25610001000(默认值为 256000000)

5.取其所需,投其所好
  • 5.1 列裁剪(只读取查询中所需要用到的列,而忽略其它列)
    例如:SELECT a,b FROM q WHERE e<10;
  • 5.2 分区裁剪(查询的过程中减少不必要的分区,只读取查询中所需要用到的分区)
    • 5.3 JOIN操作
      将条目少的表/子查询放在 Join 操作符的左边。
      原因是在 Join 操作的 Reduce 阶段,位于 Join 操作符左边的表的内容会被加载进内存,将条目少的表放在左边,可以有效减少发生 OOM(out of memory 内存溢出) 错误的几率
    • 5.4 MAP JOIN操作
      Join 操作在 Map 阶段完成,不再需要Reduce,前提条件是需要的数据在 Map 的过程中可以访问到
      相关的参数为:
      hive.join.emit.interval = 1000
      hive.mapjoin.size.key = 10000
      hive.mapjoin.cache.numrows = 10000
  • 5.5 GROUP BY操作
    进行GROUP BY操作时需要注意一下几点:
    (1)Map端部分聚合
    事实上并不是所有的聚合操作都需要在reduce部分进行,很多聚合操作都可以先在Map端进行部分聚合,然后reduce端得出最终结果。
       这里需要修改的参数为:
       hive.map.aggr=true(用于设定是否在 map 端进行聚合,默认值为真)
    hive.groupby.mapaggr.checkinterval=100000(用于设定 map 端进行聚合操作的条目数)
    (2).此处需要设定 hive.groupby.skewindata,当选项设定为 true时,生成的查询计划有两个MapReduce任务。
    在第一个MapReduce中,map的输出结果集合会随机分布到 reduce 中,每个 reduce 做部分聚合操作,并输出结果。
    这样处理的结果是,相同的 Group By Key 有可 能分发到不同的 reduce 中,从而达到负载均衡的目的;
    第二个 MapReduce 任务再根据预处 理的数据结果按照 Group By Key 分布到 reduce 中
    (这个过程可以保证相同的 Group By Key 分布到同一个 reduce 中),最后完成最终的聚合操作。
6.数据倾斜问题
  • (a).无效ID在关联时的数据倾斜问题
    日志中常会出现信息丢失,比如每日约为 20 亿的全网日志,其中的user_id为主键,在日志收集过程中会丢失,出现主键为 null 的情况,
    如果取其中的 user_id 和 bmw_users 关联,就会碰到数据倾斜的问题,
    原因:Hive 中,主键为 null 值的项会被当做相同的 Key 而分配进同一个计算 Map。
    解决方法 1:user_id 为空的不参与关联,子查询过滤 null(WHERE a.user_id IS NULL)
    解决方法 2:函数过滤 null(CASE WHEN a.user_id IS NULL THEN CONCAT(‘dp_hive’,RAND()) ELSE a.user_id END =b.user_id)
  • (b)不同数据类型关联产生的倾斜问题
    s8 的日志中有 32 为字符串商品 id,也有数值商品 id,日志中类型是 string 的,但商品中的 数值 id 是 bigint 的
    不同数据类型 id 的关联会产生数据倾斜问题
    猜想问题的原因:是把 s8 的商品id(string) 转成数值id 做 hash 来分配 Reduce,所以字符串 id 的 s8 日志,都到一个 Reduce 上了
    解决方法:把数据类型转换成字符串类型

(二)、Hive排序相关

(1).sort by排序
会产生多个reducer,每个reducer中的数据是有序的(但是并不是全局有序)
可以通过设置set mapred.reduce.tasks=2 来设置sort by时生成的reducer的个数.

(2).排序 distribute by
hive中的distribute by是控制在map端如何拆分数据给reduce端的。
hive会根据distribute by后面列,根据reduce的个数进行数据分发,默认是采用hash算法。
对于distribute by进行测试,一定要分配多reduce进行处理,否则无法看到distribute by的效果。
select *
from paixu
distribute by class
sort by class asc,chinese asc;

(3).排序 cluster by
等价于sort by + distribute by(两个排序的列必须完全一致).

(4).order by排序
只有一个reduce,做全局排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值