Hive 常用参数整理

一.引言

上周遇到了大表join大表的情况,调试了一天终于调通,期间发现对hive设置参数十分不熟悉才会导致调优花了一天时间,特此整理常用参数供以后参考。

二.场景

1.Hive 动态分区

set hive.exec.dynamic.partition.mode=nonstrict;
动态分区的好处是可以根据表字段自动将数据加入到指定分区,相比于写死固定分区更加便捷。以下实例基于your_table是单分区表。

原始分区示例:

hive -e "
insert overwrite table $your_table partition (dt='20201117')
select name,age
from $data_table
"

动态分区示例:

set hive.exec.dynamic.partition.mode=nonstrict;

hive -e "
insert overwrite table $your_table partition (dt)
select name,age,dt
from $data_table
"

2.Hive 并行执行

set hive.exec.parallel=true;

set hive.exec.parallel.thread.number=16;

第一个参数表示开启并行执行,常用语多个表join的场景,如果某几个Stage互不影响,hive就会并行执行提高执行效率。该参数默认关闭,提升效率的同时对资源的要求也会加大。

第二个参数定义了同一个sql允许最大并行度,默认为8。

如果并行执行成功,会看到类似日志,不同Stage的语句同时打在log日志里:

3.Hive 压缩

set mapreduce.map.output.compress:开启mapreduce中map输出压缩功能

set hive.exec.compress.intermediate=true: 开启传输数据压缩功能

set hive.exec.compress.output=true: 开启mapreduce最终输出数据压缩

set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec: 设置为Gzip格式压缩

set mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec: 设置为SnappyCodec压缩

最常见的需求就是select数据后无论insert到表里还是hdfs路径都将数据压缩,最终your_table会用gzip存储表数据:

hive -e "
set hive.exec.compress.output=true;
set hive.exec.compress.intermediate=true;
set hive.exec.compress.output=true;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;

insert overwrite table $your_table partition (dt=${dt})
select name,age from $data_table;
"
~

4.Hive map合并小文件

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat: 开启小文件合并

set hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat:不开启小文件合并
 

这个是上周遇到的坑之一,就是小文件太多,导致mapper的数量巨大,占用过多资源,运行至一半时被强行kill。 上面是Hive启动时mapper的数量和reduce的数量,可以看到map数量非常大,而reduce数量很少,一般遇到这种情况开启小文件合并,增加reduce数量基本可以解决问题,同时也不会出现下述问题,map reduce运行至一半kill掉。至于不开启小文件合并选项适合于单条数据量小,但数据条数很多的情况。

Hadoop job information for Stage-1: number of mappers: 68423; number of reducers: 300
FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask

上面是在map处理文件时进行小文件合并,下面的合并小文件是在输出端进行合并:

set hive.merge.mapfiles = true: 在Map-only的任务结束时合并小文件

set hive.merge.mapredfiles = true: 在Map-Reduce的任务结束时合并小文件

set hive.merge.size.per.task = 256*1000*1000: 合并文件的大小

set hive.merge.smallfiles.avgsize=16000000: 当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件merge 

5.Hive 修改mapper数量

5.1 不开启小文件合并

set dfs.block.size: 集群设置的文件块大小

不开启文件合并时会按照集群的默认设置即每一个block的大小进行mapper的计算,该参数不能在脚本自定义修改。假设有三个文件a,b,c,大小分别是1m,2m,200m,集群block.size设置多为128m,上述三个文件就会生成为4个block,大小分别为1m,2m,128m,72m。一般情况下mapper的数量就是文件块的数量,因此如果小文件过多,就会造成block数目过多,因此mapper的数量也会加大。这里有一个容易混淆的地方就是split和block,默认情况下split:block:mapper是1:1:1(ps:不是金龙鱼调和油)。经常会说一个block对应一个mapper,但其实是一个split对应一个mapper,而且一个split可能包含多个block,反之不成立。

5.2 开启小文件合并

set mapred.max.split.size=256000000: 每个Map最大输入大小 默认256000000 即256mb 增大一倍可以看到 mapper 少一倍

set mapred.min.split.size.per.node=100000000: 一个节点上split的至少的大小,决定了多个data node上的文件是否需要合并 

set mapred.min.split.size.per.rack=100000000: 一个交换机下split的至少的大小,决定了多个交换机上的文件是否需要合并

这里mapper的数量需要和上面合并小文件数量参数结合,如果设置不合并小文件,mapper的数量,如果设置了合并小文件,则会根据上述三个规则进行合并。

合并后mapper的数量:


-> 第一步:每个目录下的文件如果超过参数mapred.max.split.size的大小,则会生成 FileSize / MaxSize 个split,由于是取余这里还会空出一部分文件,这一部分文件size如果大于mapred.min.split.size.per.node中规定的minSIze,则会单独生成一个split,否则放置不动等待后续操作。由于一个split可能对应多个block,所以这里split的size可以大与block的默认size。

数学语言理解下:

FIleSize:(A)  MaxSize:(B)  固定的split数目 C = A / B 剩余的部分(D)的size : (A - B x C)  MinSizePerNode(E),如果D > E,D单独形成一个split,则共生成C+1个split,对应 C+1 个mapper,否则D先备用。


->第二步:经过上一步操作后每个目录的各个rack都留下一些文件碎片D,多个D加在一起如果超过参数mapred.max.split.size的大小,就生成一个split,这时如果剩下的碎片比mapred.min.split.size.per.rack大,就会合成一个split,否则保留。

数学语言理解下:

剩余Remaining R = ∑D,如果 R > MaxSize:(B),则生成M = R / B 个split,剩余的部分 RD = R - M x B,如果RD 大于 MinRackSIze(MR),则生成一个split,否则继续保留。


-> 第三步:现在不同rack下都留着小于mapred.min.split.size.per.rack大小的一批文件碎片,将这批碎片合并,如果大于mapred.max.split.size就合成split,此时还剩着的碎片合成最后一个split。

数学语言理解下:

上一步各rack上剩余部分RD中未生成split的部分组成一个 Mix_RD,生成 mix_RD / MaxSize:(B) 个split,再余下的合起来生成最后一个split。


操作一下:

hive参数:

set mapred.max.split.size=1000;

set mapred.min.split.size.per.node=400;

set mapred.min.split.size.per.rack=200;

输入目录:

rack1:4个文件 分别为 1000, 1001, 999, 50

rack2:2个文件 分别为 3000,1280

第一步:

rack1: Split -> 1000, 1000, 999  Fragments -> 1, 50

rack2: Split -> 1000, 1000, 1000, 1000 Fragments -> 280

共生成7个split,3个碎片均为超过mapred.min.split.size.per.node=400,保留

第二步:

50 + 1 = 51 未达到 mapred.max.split.size =1000 与 mapred.min.split.size.per.rack = 200 ,所以继续保留

280 未达到 mapred.max.split.size =1000 但达到 mapred.min.split.size.per.rack=200,所以生成split 280 不保留

第三步:

此时多个rack下碎片总和51 未达到 mapred.max.split.size =1000,直接生成split51

6.Hive 修改reduce数量

6.1 根据数据量设置reduce数量

set hive.exec.reducers.bytes.per.reducer=500000000: 设定一个reduce处理的数据量为500M

set hive.exec.reducers.max = 888: 设置一个MR最大的reduce数,默认为999

此时reduce数量为 Min(hive.exec.reducers.max ,数据总量 / hive.exec.reducers.bytes.per.reducer)

6.2 强制设置reduce数量

set mapred.reduce.tasks = 100

6.3 奇怪的知识增加了

如果又设置max 又强制设置数量超过max怎么样:

set hive.exec.reducers.max = 888;
set mapred.reduce.tasks = 2000;

max没有生效,读取了默认的配置2000,看来是真的强制设置。

7.Hive 数据倾斜

hive.groupby.skewindata = true

该参数通过两个MapReduce使得group by操作能够支持倾斜数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BIT_666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值