请你谈谈Hive优化

本文详细介绍了Hive的性能优化策略,包括join操作的优化,如小表前置和使用相同的key,以及mapjoin的运用。针对空值导致的数据倾斜问题,提出通过赋值解决。此外,讨论了如何调整mapper和reducer的数量以平衡任务负载,并在输入和输出阶段合并小文件以减少文件碎片。这些优化技巧能显著提升Hive查询的效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hive优化

1.1 join操作进行优化

join优化是个复杂的问题,可以从以下几点进行优化

1)小表前置
大小表在join的时候,应该将小表放在前面,Hive在解析带join的SQL语句时,会默认将最后一个表作为大表,将前面的表作为小表并试图将它们读进内存。如果表顺序写反,大表在前面,可能会引发OOM。

2)key值相同

多表join的时候尽量使用相同的key来关联,这样会将会将多个join合并为一个MR job来处理。

3)利用map side join

map join特别适合大小表join的情况。Hive会将大表和小表在map端直接完成join过程,消灭reduce,效率很高。Hive 0.8版本之前,需要加上map join的暗示,以显式启用map join特性,具体做法是在select语句后面增加/+mapjoin(需要广播的较小表)/。

map join的配置项是hive.auto.convert.join,默认值true;还可以控制map join启用的条件,hive.mapjoin.smalltable.filesize,当较小表大小小于该值就会启用map join,默认值25MB。

1.2 空值引起数据倾斜优化

对于空值或者无意义的值引发的数据倾斜,该怎么处理呢?

当一张表中的空值过多的时候,所有的空值都会由一个reduce执行。这时候就可以为每一个空值进行赋值,可以由一个指定的字符串+随机数的方式赋值。

1.3 如何调整mapper数?

mapper数量与输入文件的split数息息相关,可以通过设置相关参数来调整mapper数。

1)可以直接通过参数mapred.map.tasks(默认值2)来设定mapper数的期望值,但它不一定是最终mapper数;

2)输入文件的总大小为total_input_size。HDFS中,一个块的大小由参数dfs.block.size指定,默认值64MB或128MB。所以得出来的默认mapper数就是:

default_mapper_num = total_input_size / dfs.block.size,但是它也不一定是最终的mapper数;

3)设置参数mapred.min.split.size(默认值1B)和mapred.max.split.size(默认值64MB)分别用来指定split的最小和最大值。那么split大小和split数计算规则是:

split_size = MAX(mapred.min.split.size, MIN(mapred.max.split.size, dfs.block.size));

split_num = total_input_size / split_size。

4)最终得出mapper数:

mapper_num = MIN(split_num, MAX(default_mapper_num, mapred.map.tasks))。

其中可变的参数有:mapred.map.tasks、dfs.block.size(不会为了一个程序去修改,但是也算是一个可变参数)、mapred.min.split.size、mapred.max.split.size,通过调整他们来实现,mapper数的变化。

1.4 如何调整reducer数?

利用参数mapred.reduce.tasks可以直接设定reducer数量,不像mapper一样是期望值。如果不设这个参数的话,Hive就会自行推测,逻辑如下:

1)参数hive.exec.reducers.bytes.per.reducer用来设定每个reducer能够处理的最大数据量。

2)参数hive.exec.reducers.max用来设定每个job的最大reducer数量。

3)reducer数:

reducer_num = MIN(total_input_size / reducers.bytes.per.reducer, reducers.max)。

reducer数量决定了输出文件的数量。如果reducer数太多,会产生大量小文件,对HDFS造成压力。如果reducer数太少,每个reducer要处理很多数据,容易拖慢执行时间也有可能造成OOM。

1.5 什么时候又需要合并文件?如何合并小文件?

当有很多小文件的时候没需要合并小文件,可以在输入阶段合并,也可以在输出阶段合并。

1)输入阶段合并

要想文件自动合并,需要更改Hive的输入文件格式,通过参数hive.input.format来更改,默认值是org.apache.hadoop.hive.ql.io.HiveInputFormat,需要改成org.apache.hadoop.hive.ql.io.CombineHiveInputFormat。还需要设置mapred.min.split.size.per.node和mapred.min.split.size.per.rack这两个参数,他们的含义是单节点和单机架上的最小split大小。设置完后,如果发现有split大小小于这两个值(默认都是100MB),则会进行合并。

2)输出阶段合并

设置hive.merge.mapfiles为true可以将map-only任务的输出合并;

设置hive.merge.mapredfiles为true可以将map-reduce任务的输出合并。另外,设置hive.merge.size.smallfiles.avgsize可以指定所有输出文件大小的均值阈值,一旦低于这个阈值,就会启动一个任务来进行合并。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值