hive参数调优

集群最优配置的最好方式是通过实验测试,然后衡量结果。

普通配置

--元数据连接超时
set hive.metastore.client.socket.timeout=500;
--指定MR任务运行队列
set mapreduce.job.queuename=bigdata;
--指定作业名称,如果脚本中有多个sql语句,那么你设定jobname后,所有的sql生成的job都会有同一个名字
set mapred.job.name=jobname;

并行化配置

hive默认job是顺序进行的,一个HQL拆分成多个job,job之间无依赖关系也没有相互影响可以并行执行
set hive.exec.parallel=true;
--控制对于同一个sql来说同时可以运行的job的最大值,该参数默认为8.此时最大可以同时运行8个job
set hive.exec.parallel.thread.number=8;

本地化配置:

在存放数据的节点上执行
set hive.exec.mode.local.auto=true;
--本地化执行必须满足条件:1)job的输入数据大小必须小于参数
hive.exec.mode.local.auto.inputbytes.max(默认128MB)
(2)job的map数必须小于参数:
hive.exec.mode.local.auto.tasks.max(默认为4)太多没有足够的slots
(3)job的reduce数必须为01

输入小文件配置

--job合并输入小文件
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
--多个split合成一个,合并split数由mapred.max.split.size限制的大小决定

输出小文件配置

--HIVE自动合并输出小文件的主要优化手段为:
--在只有map的作业结束时合并小文件
set hive.merge.mapfiles = true;
--在Map-Reduce的任务结束时合并小文件,默认为False;
set hive.merge.mapredfiles = true;
--当输出文件的平均大小小于该值时并且(mapfiles和mapredfiles为true)
set hive.merge.smallfiles.avgsize=256000000;
--这个参数设置为true,orc文件进行stripe Level级别的合并,当设置为false,orc文件进行文件级别的合并
set hive.merge.orcfile.stripe.level=false;

动态分区配置

--开启动态分区
set hive.exec.dynamic.partition=true;  
--默认值是strict,就是要求分区字段必须有一个是静态的分区值,设置为nonstrict,那么可以全部动态分区
set hive.exec.dynamic.partition.mode=nonstrict;
--被一条有动态分区的SQL语句所能创建的动态分区总量,超出报错。
SET hive.exec.max.dynamic.partitions=100000;
--能被每个mapper或reducer创建的最大动态分区的数目。
SET hive.exec.max.dynamic.partitions.pernode=100000;
--举例: 动静并存 指明需要静态分区的字段值,剩下的字段就属于动态分区了
--这里指将2017年5月份的数据插入分区表,对应底层的物理操作就是讲2017年5月份的数据load到hdfs上对应2017年5月份下的所有day和hour目录中去
insert overwrite table device_open partition(year='2017',month='05',day,hour)
--默认为false,如果为true的话,这个参数可以使得每个分区只产生一个文件
--可以解决动态分区时的OOM问题,但会严重降低reduce处理并写入一个分区的速度
set hive.optimize.sort.dynamic.partition=true;

压缩配置:

--map/reduce 输出压缩(一般采用序列化文件存储)
set hive.exec.compress.output=true;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;--最终输出用gzip好,减少储存空间。
set mapred.output.compression.type=BLOCK;
--任务中间对数据压缩
set hive.exec.compress.intermediate=true;
set hive.intermediate.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;--中间压缩常用SnappyCodec ,CPU消耗较低
set hive.intermediate.compression.type=BLOCK;--按块压缩,而不是记录

什么情况使用hive压缩?

1)在hadoop作业执行过程中,job执行速度更多的是局限于I/O,而不是受制于CPU。
压缩格式?
(1)GZip 和 BZip2压缩格式是所有最近的hadoop版本支持的,而且linux本地的库也支持这种格式的压缩和解压缩。
(2)Snappy是最近添加的压缩格式,可以自己添加这种压缩格式。
(3)LZO是经常用到的压缩格式
压缩优缺点:
(1)GZip 和 BZip2压缩可以保证最小的压缩文件,但是过于消耗时间; Snappy和LZO压缩和解压缩很快,但是压缩的文件较大。所以如何选择压缩格式,需要根据具体的需求决定。(I/O,CPU)
(2)BZip2 and LZO支持压缩文件分割

JVM重利用

--每个jvm运行多少个task;
set mapred.job.reuse.jvm.num.tasks=20;
--JVM重利用可以使job长时间保留slot,直到作业结束

map端聚合

--将顶层的聚合操作(指在group by语句之前执行的聚合操作)放在Map阶段执行,缺点:该设置会消耗更多的内存
set hive.map.aggr=true;
--推测执行(默认为true),解决一些bug时可能需要关闭task推测执行。
set mapred.map.tasks.speculative.execution=false;
set mapred.reduce.tasks.speculative.execution=false;
--每个reduce任务处理的数据量,默认为1000^3=1G
set hive.exec.reducers.bytes.per.reducer=256000000;
--默认值是10000,如果你的表有60个分区,然后你有2000个map,在运行的时候,每一个mapper都会创建60个文件,对应着每一个分区,所以60*2000> 120000,就会报错:exceeds 100000.Killing the job
set hive.exec.max.created.files=100000;

map端JOIN

SET hive.auto.convert.join=true; --  hivev0.11.0之后默认true
SET hive.mapjoin.smalltable.filesize=600000000; -- 默认 25m
SET hive.auto.convert.join.noconditionaltask=true; -- 默认true,所以不需要指定map join hint
SET hive.auto.convert.join.noconditionaltask.size=10000000; -- 控制加载到内存的表的大小

hive map 优化

--直接set mapred.map.tasks=10 可能是无效的。
set mapred.map.tasks=10
--hive map数计算方式:1)默认map个数
default_num=total_size/block_size;
 (2)期望大小(手动设置的个数)
goal_num =mapred.map.tasks;3)设置处理的文件大小(根据文件分片大小计算的map个数)
split_size=max(block_size,mapred.min.split.size);
split_num=total_size/split_size;4)最终计算的map个数(实际map个数)
compute_map_num=min(split_num,max(default_num,goal_num))
--hive map数设置方式:1)如果想增加map个数,则设置mapred.map.tasks为一个较大的值;
(2)如果想减小map个数,则设置mapred.min.split.size为一个较大的值。

hive shuffle优化

Map 端
--默认值缓存区是100M
set io.sort.mb=100;
--达到缓存区80%开始溢写
set io.sort.spill.percent=0.8
--
min.num.spill.for.combine
--
io.sort.factor
--
io.sort.record.percent
reduce端
mapred.reduce.parallel.copies
mapred.reduce.copy.backoff
io.sort.factor
mapred.job.shuffle.input.buffer.percent

hive reduce优化

--推测执行(默认为true),解决一些bug时可能需要关闭task推测执行。
set mapred.map.tasks.speculative.execution=false;
set mapred.reduce.tasks.speculative.execution=false;
--reduce个数设置
set mapred.reduce.tasks=10;直接设置

--最大值,默认:999
set hive.exec.reducers.max=999;

--每个reducer计算的文件量大小, 默认:1G
set hive.exec.reducers.bytes.per.reducer=;

--hive reduce数计算方式:
maxReducers=hive.exec.reducers.max
perReducer=hive.exec.reducers.bytes.per.reducer
numRTasks =min[maxReducers,input.size/perReducer]

数据倾斜配置

数据倾斜时负载均衡,当选项设定为true,生成的查询计划会有两个MRJob。第一个MRJob 中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的GroupBy Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;第二个MRJob再根据预处理的数据结果按照GroupBy Key分布到Reduce中(这个过程可以保证相同的GroupBy Key被分布到同一个Reduce中),最后完成最终的聚合操作
set hive.groupby.skewindata=true;
set hive.groupby.mapaggr.checkinterval =100000;

作业运行内存配置

--针对mapreduce任务,所有有关内存的参数配置。
--yarn上运行程序时每个task都是在独立的Container中运行的,单个Container可以申请的最小和最大内存的限制
yarn.scheduler.minimum-allocation-mb
yarn.scheduler.maximum-allocation-mb
--这台服务器节点上准备分给yarn的内存
yarn.nodemanager.resource.memory-mb 

yarn.nodemanager.vmem-pmem-ratio

yarn.scheduler.increment-allocation-mb
--打算给单个map/reduce任务申请内存资源”,注意其值不要超过yarn.scheduler.maximum-allocation-mb
set mapreduce.map.memory.mb=8192;
set mapreduce.reduce.memory.mb=8192;
--执行一个脚本文件时会执行Java 的子进程,这个子进程就是真正的 Map Task,其实就是启动 JVM 虚拟机时,传递给虚拟机的启动参数,
--表示这个 Java 程序可以使用的最大堆内存数。一旦超过这个大小,JVM 就会抛出 Out of Memory 异常,并终止进程。
--mapreduce.map.java.opts一定要小于mapreduce.map.memory.mb
set mapreduce.map.java.opts=-Xmx6144m;
set mapreduce.reduce.java.opts=-Xmx6144m;

抽样查询

--抽样查询:TableSample   按桶抽样
SELECT * from numbers TABLESAMPLE(BUCKET 3 OUT OF 10 ONrand()) s;
--按块进行抽样按块抽样的最小抽样单元是一个HDFS的块,默认情况下,如果表的大小小于128MB,那么所有的列将会被抽出,无论设置的百分比是多少
SELECT * FROM numbers flat TABLESAMPLE(0.1 PERCENT) s;

Hive中小文件问题:

Hive里面什么时候会产生大量小文件呢?
(1)一个大文件使用动态分区,可能导致大量分区产生,从而产生多很多小文件,也会导致很多的mapper
(2)Reduce个数越多,小文件越多,Reduce个数和输出文件是一样的
(3)数据源本身就包含很多的小文件

解决小文件的问题

1)果动态分区不可预知的情况下,最好别用,如果用也最好distributedby 分区字段,这样我们知道会对字段进行一个hash操作,这样就会把相同的相同的分区给同一个Reduce去处理
(2)如果Reduce数量太多,则减少reduce的数量
(3)进行一些参数设置,设置 mapper输入文件合并一些参数

动态分区插入时OOM问题

1)修改参数hive.optimize.sort.dynamic.partitiontrue。产生OOM问题的原因是同时打开了太多写分区的record,
    writer同时写入文件,开启该参数的话,分区列会全局排序,使得reduce端每个分区只有一个文件写入,降低reduce的内存压力
(2)要是还报OOM问题,进一步可以考虑调整map、reduce的内存大 mapreduce.map.memory.mb 和 mapreduce.reduce.memory.mb 参数

常用函数-时间函数

--获取当前时间
SUBSTR(CURRENT_TIMESTAMP(), 1, 19) AS MAKE_TIME
--使用datediff函数求两个指定日期的差
datediff(endDate, startDate)
--查询近30天的数据
where datediff(current_timestamp,create_time)<=30--日期增加函数:
date_add('2016-12-29',10);  2017-01-08
--日期减少函数
date_sub('2016-12-29',10); 2016-12-19

你可能感兴趣的:(hive,Hadoop,linux,hdfs,hadoop)