Hive面试题2:常用hive配置

 

1.启用动态分区

对分区表Insert数据时候,数据库自动会根据分区字段的值,将数据插入到相应的分区中。

SET hive.exec.dynamic.partition=true;  
SET hive.exec.dynamic.partition.mode=nonstrict; 
SET hive.exec.max.dynamic.partitions.pernode = 1000;--根据实际情况
SET hive.exec.max.dynamic.partitions=1000;--根据实际情况
SET hive.optimize.sort.dynamic.partition=true; --若输出为parquet表且需要输出到多个分区时

相关参数:

  • hive.exec.dynamic.partition

默认值:false

是否开启动态分区功能,默认false关闭。

使用动态分区时候,该参数必须设置成true;

  • hive.exec.dynamic.partition.mode

默认值:strict

动态分区的模式,默认strict,表示必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区。

一般需要设置为nonstrict

  • hive.exec.max.dynamic.partitions.pernode

默认值:100

在每个执行MR的节点上,最大可以创建多少个动态分区。

该参数需要根据实际的数据来设定。

比如:源数据中包含了一年的数据,即day字段有365个值,那么该参数就需要设置成大于365,如果使用默认值100,则会报错。

  • hive.exec.max.dynamic.partitions

默认值:1000

在所有执行MR的节点上,最大一共可以创建多少个动态分区。

同上参数解释。

  • hive.exec.max.created.files

默认值:100000

整个MR Job中,最大可以创建多少个HDFS文件。

一般默认值足够了,除非你的数据量非常大,需要创建的文件数大于100000,可根据实际情况加以调整。

  • hive.error.on.empty.partition

默认值:false

当有空分区生成时,是否抛出异常。

一般不需要设置。

  • hive.optimize.sort.dynamic.partition

默认值:false

明白这个参数的含义就要了解动态分区的实现原理,以及为什么动态分区默认是关闭的。

hive 默认的动态分区实现,不需要shuffle,既是map only job。这时分区字段(比如日期)是未排序的,如果分区数目较多,一个map每读到一个日期值,就要打开一个file writer。假如map数和分区数都很大,可能会超过datanode最大打开句柄数。也就是为什么hive 严格模式是禁止用动态分区的,就算关闭严格模式,也是限制job最大写分区数的,甚至限制每台节点写分区数,就是怕某个动态分区的hive任务把系统的文件句柄耗光,影响其他任务的正常运行。

此参数为true时,由于分区字段是排序的,因此每个reducer只需要保持一个文件写入器(file writer)随时处于打开状态,在收到来自特定分区的所有行后,关闭记录写入器(record writer)。1.极大减少了文件句柄数; 2.Parquet和ORC是列式批处理文件格式。这些格式要求在写入文件之前将批次的行(batches of rows)缓存在内存中。在执行INSERT语句时,动态分区目前的实现是:至少为每个动态分区目录打开一个文件写入器(file writer)。由于这些缓冲区是按分区维护的,因此在运行时所需的内存量随着分区数量的增加而增加。所以经常会导致mappers或reducers的OOM,具体取决于打开的文件写入器(file writer)的数量。参考https://www.cnblogs.com/jiangxiaoxian/archive/2004/01/13/9565500.htmlhttps://blog.csdn.net/frank_jyp/article/details/81780821

2.mapreduce参数

当默认mapreduce参数无法满足需要时,也可以在sql里修改。经常修改的参数:

SET mapreduce.map.memory.mb=4096;--map container内存
SET mapreduce.map.java.opts=-Xmx3584m; --map jvm内存
SET mapreduce.reduce.memory.mb=4096;--reduce container内存
SET mapreduce.reduce.java.opts=-Xmx3584m; --reduce jvm内存
SET mapreduce.job.reduces=666; --reducer数目
SET mapred.job.reuse.jvm.num.tasks=5;; --task执行完毕后,jvm会退出。如果任务花费时间很短,又要多次启动 JVM 的情况下,JVM 的启动时间会变成一个比较大的消耗, 这个时候,就可以通过重用 JVM 来解决。

3.数据倾斜

大数据处理的一大天敌。

  • group by聚合倾斜

set hive.map.aggr=true;--开启map端聚合 默认为true

set hive.groupby.skewindata=true; --查询计划会有两个MR Job。当第一个MR Job中,Map的输出结果结合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果。这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的。第二个MR Job再根据预处理的数据结果按照Group By Key分布到reduce中,这个过程可以保证相同的key被分到同一个reduce中,最后完成最终的聚合操作。

  • 空值关联

a.关联key为空的不参与关联; b.为空值key赋予新的随机值,把造成倾斜的数据分到不同reducer上,并且由于随机值关联不上,并不影响最终结果。select * from a left join b on nvl(a.id, concat('hive', rand())) = b.id;

  • 大表join小表

开启mapjoin。

在早起hive版本不能自动优化map join,需要在select 关键词后主动添加提示优化器:

select /* +mapjoin(a) */ a.id aid, name, age from a join b on a.id = b.id;

--在0.11版本后,mapjoin hint默认关闭了,如想继续使用,需要加参数:

set hive.ignore.mapjoin.hint=false;

 

 

hive 0.11版本后,会自动开启mapjoin优化,由两个参数控制:

set hive.auto.convert.join=true; //设置 MapJoin 优化自动开启,默认即为true,无需添加

set hive.mapjoin.smalltable.filesize=25000000; //设置小表不超过多大时开启 mapjoin 优化,默认值,日常使用可以调大测试

set hive.auto.convert.join.noconditionaltask=true; //默认即为true

set hive.auto.convert.join.noconditionaltask.size=10000000; //默认10M,实际可以调大测试,实测800M可行。另外当hive on spark时要适当调大,因为hive on mr时估计文件大小,on spark时按内存占用判断是否转为mapjoin

mapjoin的原理是把小表放到distribute cache中,再执行mapredlocaltask。如果滥用mapjoin,localtask会出现内存溢出,导致任务失败。

 

Hive Runtime Error: Map local work exhausted memory
org.apache.hadoop.hive.ql.exec.mapjoin.MapJoinMemoryExhaustionException: 2021-02-05 00:13:12	Processing rows:	1500000	Hashtable size:	1499999	Memory usage:	7093884064	percentage:	0.556
	at org.apache.hadoop.hive.ql.exec.mapjoin.MapJoinMemoryExhaustionHandler.checkMemoryStatus(MapJoinMemoryExhaustionHandler.java:99)
	at org.apache.hadoop.hive.ql.exec.HashTableSinkOperator.process(HashTableSinkOperator.java:253)
	at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:838)
	at org.apache.hadoop.hive.ql.exec.FilterOperator.process(FilterOperator.java:122)
	at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:838)
	at org.apache.hadoop.hive.ql.exec.TableScanOperator.process(TableScanOperator.java:97)
	at org.apache.hadoop.hive.ql.exec.mr.MapredLocalTask.startForward(MapredLocalTask.java:407)
	at org.apache.hadoop.hive.ql.exec.mr.MapredLocalTask.startForward(MapredLocalTask.java:378)
	at org.apache.hadoop.hive.ql.exec.mr.MapredLocalTask.executeInProcess(MapredLocalTask.java:344)
	at org.apache.hadoop.hive.ql.exec.mr.MapredLocalTask.execute(MapredLocalTask.java:141)
	at org.apache.hadoop.hive.ql.exec.Task.executeTask(Task.java:163)
	at org.apache.hadoop.hive.ql.exec.TaskRunner.runSequential(TaskRunner.java:90)
	at org.apache.hadoop.hive.ql.Driver.launchTask(Driver.java:1695)
	at org.apache.hadoop.hive.ql.Driver.execute(Driver.java:1452)
	at org.apache.hadoop.hive.ql.Driver.runInternal(Driver.java:1236)
	at org.apache.hadoop.hive.ql.Driver.run(Driver.java:1085)
	at org.apache.hadoop.hive.ql.Driver.run(Driver.java:1080)
	at org.apache.hive.service.cli.operation.SQLOperation.runQuery(SQLOperation.java:205)
	at org.apache.hive.service.cli.operation.SQLOperation.access$100(SQLOperation.java:73)
	at org.apache.hive.service.cli.operation.SQLOperation$1$1.run(SQLOperation.java:256)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAs(Subject.java:422)
	at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1901)
	at org.apache.hive.service.cli.operation.SQLOperation$1.run(SQLOperation.java:268)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

4.小文件合并

小文件就是指,在HDFS上落地的文件大小远远小于一个Block块大小(hadoop2.x是128M)的文件。小文件存储在HDFS上,对应的每个文件都会在namenode中存有相应的元数据信息(在namenode的内存中均被表示为一个对象(object)).如果每一个文件的元数据信息占用内存100byte,那么有10万个文件, 就占用了namenode10G的内存空间 * **数据查询** HDFS对小文件的读取, 涉及到磁盘读取, 同时涉及到从跨datanode的文件查询(Reading through small files normally causes lots of seeks and lots of hopping from datanode to datanode to retrieve each small file)。从hive访问角度,每个文件需要起一个map task来访问,当小文件很多时,会浪费很多时间在task的启动上,但是实际执行时间很短。

为了让下游任务执行更高效,需要对小文件进行合并。

set hive.merge.mapredfiles=true; //在map reduce job结束时合并小文件

set hive.merge.sparkfiles=true; //hive on spark时替换hive.merge.mapredfiles,在spark执行结束时合并小文件

set hive.merge.mapfiles=true; //默认即为true, 在map-only job结束时合并小文件

set hive.merge.smallfiles.avgsize=16*1000*1000; //默认16M,定义了小文件的概念。当输出文件平均大小小于16M时,启动一个独立的map-reduce任务合并文件。

set hive.merge.size.per.task=256*1000*1000; //默认256M,合并后的文件多大

 

 

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值