Hive调优实操(不断更新中…)

前提条件:知道mapreduce的原理及代码实现,知道常用的hivesql(比如join、count(distict))在底层mapreduce是怎么实现的,知道怎么看执行计划,知道yarn的resouce manager webUI的界面数据的含义。
1、explain+语句:查看sql对应的mapreduce的stage
2、看执行计划的STAGE DEPENDENCIES:理清stage的DAG图
3、通过日志给出的track_url查看resouce manager webUI界面对应的job信息

参考:
https://blog.youkuaiyun.com/u012151684/article/details/77074356(通俗易懂)
https://blog.youkuaiyun.com/qq_37142346/article/details/89852906
《Hive性能调优实战》

Hive调优逻辑

充分理解业务的情况下,基于对于Hadoop计算引擎和原理的理解,结合执行计划和yarn日志,通过优化sql、改变数据块大小、改变数据的存储结构和表设计来对hivesql进行优化

Map阶段调优

出发点:在调优时我们不希望生成太多的Map,计算任务的等待时间都耗费在Map 的启动上,或者不希望生成太多的Map 对某个文件进行操作,以免引起资源的争用;但map数量也不能太少,太少就无法充分利用大数据集群的并发性。这时候就需要对Map进行控制

方法一:调整map个数

Map数算法:

default_num = totalSize / blockSize;
goal_num = mapred.map.tasks;
split_num = totalSize/max(mapred.min.split.size, blockSize);
compute_map_num = min(split_num, max(default_num, goal_num))
final_map_num = max(compute_map_num, input_file_num)
备注:
totalSize为目标文件或数据的总大小
blockSize为hdfs集群文件块的大小
mapred.map.tasks为用户自定义的map数
mapred.min.split.size为文件分片的大小
input_file_num为输入文件的个数
mapreduce的每一个map处理的数据是不能跨越文件的,也就是说min_map_num >= input_file_num

经过以上的分析,在设置map个数的时候,可以简单的总结为以下几点:
(1)如果想增加map个数,则设置mapred.map.tasks 为一个较大的值。
(2)如果想减小map个数,则设置mapred.min.split.size 为一个较大的值。
(3)如果输入中有很多小文件,依然想减少map个数,则需要将小文件merger为大文件,然后使用准则补充:合并输入小文件方法(小文件启动时间很长实际执行时间很短,集群资源无法很好地被利用)

set hive.input.format=oar.apache.hadoop.hive.ql.io.CombineHiveInputFormat
合并输出小文件
set hive.merge.smallfiles.avgsize=256000000当输出文件平均大小小于256mb时,启动新job合并文件
set hive.merge.size.per.task=64000000设定合并之后的文件大小)
方法二:其他map阶段的优化方式

1、set hive.vectorized.execution.enabled=true; 开启向量模式,从逐行处理数据变更为批量处理数据
2、开启mapjoin

方法一:手动指定/*+MAPJOIN(小表表名)/
方法二:自动开启
set hive.auto.convert.join=true
set hive.mapjoin.smalltable.filesize=25000000 (当文件大小小于25MB时就是小表)
set hive.mapjoin.cache.numrows=25000(mapjoin时存在内存中的数据量小于25000行)
set hive.mapjoin.followby.gby.localtask.max.memory.usage
set hive.mapjoin.localtask.max.memory.usage

3、开启map端聚合,目的减少Map任务的输出,从而减少shuffle过程的数据量

Set hive.map.aggr=true;
Set hive.map.aggr.hash.min.reduction=0.5;将聚合后的数据除以聚合前的数据,如果小于hive.map.aggr.hash.min.reduction会自动关闭

3、对中间结果进行压缩,减少shuffle过程的数据量

Set hive.exec.compress.intermediate=true --对中间结果压缩
set hive.intermedia.compression.codec=org.apache.hadoop.io.compress.SnappyCode
set hive.intermedia.compression.type=BLOCK(按照块进行压缩)
#最终输出的压缩
set hive.exec.compress.output=true;
set hive.intermedia.compression.codec=org.apache.hadoop.io.compress.GzipCode
set hive.intermedia.compression.type=BLOCK(按照块进行压缩)
Reduce阶段调优
 set mapred.reduce.tasks
 set hive.exec.reducers.bytes.per.reducer
全局调优

1、开启并行执行

set hive.exec.parallel=true开启并行执行
set hive.exec.parallel.thread.number=16 #并行执行的线程数为16

2、避免不必要mr

 set hive.fetch.task.conversion=more

3、jvm重用,减少jvm启动的开销

set mapred.job.reuse.jvm.num.tasks=10;

使得JVM实例在同一个JOB中重新使用10次,常用于小文件的场景和task比较多的场景,不适用于有reduce的任务
4、开启推测执行
优点可以缓解数据倾斜(为什么嘛?),缺点是会启动很多任务,占用资源
5、开启本地执行

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

只有满足一下条件才能真正使用本地模式:

  • job的输入数据大小必须小于参数
  hive.exec.mode.local.inputbytes.max(默认为128M)
  • job的map数必须小于参数
  hive.exec.mode.local.auto.tasks.max(默认是4)
  • job的reduce数量必须是0或者1

6、合并输入小文件(小文件启动时间很长实际执行时间很短,集群资源无法很好地被利用)

set hive.input.format=oar.apache.hadoop.hive.ql.io.CombineHiveInputFormat

7、合并输出小文件

 set hive.merge.smallfiles.avgsize=256000000当输出文件平均大小小于256mb时,启动新job合并文件
 set hive.merge.size.per.task=64000000设定合并之后的文件大小

8、调整reduce、map执行的内存大小

Set mapreduce. reduce.memory.mb
Set mapreduce.map.memory. mb
Shuffle阶段优化

该阶段有大量读写磁盘和网络IO操作,是整个mapreduce主要性能瓶颈所在

数据倾斜

表现:由于数据分布不均匀,导致数据大量的集中到某一点上,造成数据热点。
map阶段快,reduce阶段非常慢;有些map很快,有些map很慢;某些reduce很快,某些reduce极慢
原因:
1、数据在节点上分布不均匀
2、join时on关键字个别值很大(如null值)
3、count(distinct ),在数据量大的情况下,容易数据倾斜,因为是按group by字段分组,按distinct字段排序
解决方法:
1、开启负载均衡

 hive.groupby.skewindata = false

原理,利用两个mr,第一个mr将key打散进行预聚合,第二个mr基于第一个结果按key进行聚合

2、两表链接时倾斜
2.1、用小表join大表的方式,将key相对分散的表作为左表,做好where条件过滤,尽可能只抽取有用的字段
2.2、把join条件一样的放在一个job里
2.3、开启map端join:
方法一:手动指定/*+MAPJOIN(小表表名)/
方法二:自动开启

set hive.auto.convert.join=true
set hive.mapjoin.smalltable.filesize=25000000 (当文件大小小于25MB时就是小表)
set hive.mapjoin.cache.numrows=25000(mapjoin时存在内存中的数据量小于25000行)
set hive.mapjoin.followby.gby.localtask.max.memory.usage
set hive.mapjoin.localtask.max.memory.usage

2.4、大表join:
方法一:直接过滤掉空值
方法二:把空值的key变成字符串加上随机数
方法三:先对大表进行分桶,然后启用分桶join

set hive.enforce.sortmergebucketmapjoin=true

3、count(distinct 字段名)时倾斜
方法一:先过滤掉空值,进行count(distinct),最终结果再加1
方法二:开启map端聚合

set hive.map.aggr=true开启map端聚合
set hive.groupby.mapaggr.checkinterval=100000在Map端进行聚合操作的条目

1、With cube多维聚合数据膨胀引起的数据倾斜
hive.new.job.grouping.set.cardinality
2、不可拆分大文件引发的数据倾斜
GZIP大的压缩文件,只能启动一个map来读取,在数据压缩的时候可以采用bzip2和Zip等支持文件分割的压缩算法

hive表的存储格式

textfile:默认格式,行存储,数据不做压缩,磁盘开销大,数据解析开销大
rcfile:列式存储
orc:列式存储,压缩比高、更少的IO操作读取效率高,数据量很大且数据字段数目很多,但每次查询数据只针对其中的少数几行,这时候列式存储是极佳的选择
parquet

hive的拉链表

实现思路
通过在记录末尾增加start_date和end_date字段来实现;
同一ID按时间排序后,如果有较新的记录,则当前记录的end_date等于较新记录的start_date-1,如果没有较新的记录,则当前记录的end_date等于一个默认值,比如99991231
实现代码
http://cxy7.com/articles/2018/05/25/1527237216341.html

udf、udaf、udtf

udf:继承UDF类,添加方法 evaluate()
可以用来计算活跃天数、ip地址解析、对手机号、身份证等用户等敏感信息进行加密

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值