Hive 统计优化
在数据量非常大的时候,distinct会将所有的统计信息加载到一个reducer里取执行,这就是所谓的数据倾斜。而group by会把相同key的记录放到一个reducer区计算,因此效率会提高很多。
不用数据类型造成的倾斜
空值或者大量重复着造成的倾斜,给于rand()
列裁剪
分区裁剪
Mapper join
有子查询的选择过滤掉不需要的列,提升效率
复杂逻辑python实现的优化
简单快速
Join优化特例
相同的join key 只需要一个task,大大提升了时间
Left semi join 优化 sql exists替代
返利166多T
Apache 33T
Varnish 17T
hive 调优过程
语法层面
参数层面
1 逻辑代码调整
(1)规范sql
(2)查看执行计划,分析表数据, 减少jobs数,设置合理的map reduce的task数,能有效提升性能
(3)解决数据倾斜问题
通用算法set hive.groupby.skewindata=true,
数据量较大的情况下,慎用count(distinct),count(distinct)容易产生倾斜问题
如统计淘宝一天uv,30亿的pv ,按照性别统计分配2个reduce,每个reduce处理15亿数据 ,那么可以根据性别和userid 分组排序统计
数据倾斜是导致效率大幅降低的主要原因,可以采用多一次 Map/Reduce 的方法, 避免倾斜
避实就虚,用 job 数的增加,输入量的增加,占用更多存储空间,充分利用空闲 CPU 等各种方法,分解数据倾斜造成的负担
空值填充,数据转换造成的倾斜解决
--问题
[if !supportLists]· [endif]数据量大不是问题,数据倾斜是个问题。
[if !supportLists]· [endif]jobs数比较多的作业运行效率相对比较低,比如即使有几百行的表,如果多次关联多次汇总,产生十几个jobs,耗时很长。原因是map reduce作业初始化的时间是比较长的。
[if !supportLists]· [endif]sum,count,max,min等UDAF,不怕数据倾斜问题,hadoop在map端的汇总合并优化,使数据倾斜不成问题。
[if !supportLists]· [endif]count(distinct ),在数据量大的情况下,效率较低,如果是多count(distinct )效率更低,因为count(distinct)是按group by 字段分组,按distinct字段排序,一般这种分布方式是很倾斜的。举个例子:比如男uv,女uv,像淘宝一天30亿的pv,如果按性别分组,分配2个reduce,每个reduce处理15亿数据。
面对这些问题,我们能有哪些有效的优化手段呢?下面列出一些在工作有效可行的优化手段:
[if !supportLists]· [endif]良好的sql 书写习惯,如数据类型转换问题
[if !supportLists]· [endif]解决数据倾斜问题。
[if !supportLists]· [endif]减少job数。
[if !supportLists]· [endif]设置合理的map reduce的task数,能有效提升性能。(比如,10w+级别的计算,用160个reduce,那是相当的浪费,1个足够)。
[if !supportLists]· [endif]了解数据分布,自己动手解决数据倾斜问题是个不错的选择。set hive.groupby.skewindata=true;这是通用的算法优化,但算法优化有时不能适应特定业务背景,开发人员了解业务,了解数据,可以通过业务逻辑精确有效的解决数据倾斜问题。
[if !supportLists]· [endif]数据量较大的情况下,慎用count(distinct),count(distinct)容易产生倾斜问题。
[if !supportLists]· [endif]对小文件进行合并,是行至有效的提高调度效率的方法,假如所有的作业设置合理的文件数,对云梯的整体调度效率也会产生积极的正向影响。
[if !supportLists]· [endif]优化时把握整体,单个作业最优不如整体最优。
配置角度优化
列裁剪
Hive 在读数据的时候,可以只读取查询中所需要用到的列,而忽略其它列,节省了读取开销,中间表存储开销和数据整合开销。
裁剪所对应的参数项为:hive.optimize.cp=true(默认值为真)
分区裁剪
分区参数为:hive.optimize.pruner=true(默认值为真)
Join
多个join 条件相同的可以形成只查询之后再jion 减少jobs数 提高执行效率
Mapjoin
set hive.auto.convert.join=true;
sethive.mapjoin.smalltable.filesize=3000000;
sethive.auto.convert.join.noconditionaltask=true;
sethive.auto.convert.join.noconditionaltask.size=3000000;
hive.join.emit.interval= 1000
hive.mapjoin.size.key =10000
hive.mapjoin.cache.numrows= 10000
group by 操作
Map端部分聚合
hive.map.aggr=true(用于设定是否在 map 端进行聚合,默认值为真) hive.groupby.mapaggr.checkinterval=100000(用于设定 map 端进行聚合操作的条目数)
有数据倾斜时进行负载均衡
hive.groupby.skewindata,当选项设定为 true 是,生成的查询计划有两 个 MapReduce 任务。在第一个MapReduce 中,map 的输出结果集合会随机分布到 reduce中, 每个 reduce 做部分聚合操作,并输出结果。这样处理的结果是,相同的 Group By Key 有可 能分发到不同的 reduce 中,从而达到负载均衡的目的;第二个MapReduce 任务再根据预处 理的数据结果按照 Group By Key 分布到 reduce中(这个过程可以保证相同的 Group By Key 分布到同一个 reduce中)
合并小文件
我们知道文件数目小,容易在文件存储端造成瓶颈,给 HDFS 带来压力,影响处理效率。对此,可以通过合并Map和Reduce的结果文件来消除这样的影响。
用于设置合并属性的参数有:
是否合并Map输出文件:hive.merge.mapfiles=true(默认值为真)
是否合并Reduce 端输出文件:hive.merge.mapredfiles=false(默认值为假)
合并文件的大小:hive.merge.size.per.task=256*1000*1000(默认值为 256000000)
程序角度优化
熟练sql,写出高效率的查询
空值赋予随机值
不同数据类型关联转为同一数据类型
巧用临时表
Union all 并行设置
优化常用手段
[if !supportLists]· [endif]hive.exec.reducers.bytes.per.reducer
#这个参数控制一个job会有多少个reducer来处理,依据的是输入文件的总大小。默认1GB。
[if !supportLists]· [endif]hive.exec.reducers.max #这个参数控制最大的reducer的数量, 如果 input / bytes per reduce > max 则会启动这个参数所指定的reduce个数。 这个并不会影响mapre.reduce.tasks参数的设置。默认的max是999。
[if !supportLists]· [endif]mapred.reduce.tasks #这个参数如果指定了,hive就不会用它的estimation函数来自动计算reduce的个数,而是用这个参数来启动reducer。默认是-1
参数设置
如果reduce太少:如果数据量很大,会导致这个reduce异常的慢,从而导致这个任务不能结束,也有可能会OOM 2、如果reduce太多: 产生的小文件太多,合并起来代价太高,namenode的内存占用也会增大。如果我们不指定mapred.reduce.tasks, hive会自动计算需要多少个reducer。
网友评论