您的位置:首页 > 其它

Hive优化总结

2016-03-12 19:44 260 查看

1.Hive表优化

1.1 分区

分区是以字段的形式在表结构中存在,通过describe table命令可以查看到字段存在, 但是该字段不存放实际的数据内容,仅仅是分区的表示(伪列)。

1.1.1静态分区

create table if not exists tablename(id int,name string,tel string)
partitioned by(dt string)
row format delimited
fields terminated by '\t'
stored as textfile;


1.1.2动态分区

使用动态分区前,需要配置以下参数:

hive.exec.dynamic.partition:在DML/DDL中是否支持动态分区,配置为true

hive.exec.dynamic.partition.mode:默认strict,在strict模式下,动态分区的使用必须在一个静态分区确认的情况下,其他分区可以是动态,可以考虑配置成nostrict。

1.2 分桶

使用分桶前,需要配置以下参数:

hive.enforce.bucketing:数据分桶是否被强制执行,默认false,如果开启,则写入table数据时会启动分桶。

hive.enforce.sorting:开启强制排序时,插数据到表中会进行强制排序,默认false;

对于每一个表(table)或者分区, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive也是 针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。

2. Hive查询优化

2.1 join优化

2.1.1 和数据倾斜有关的优化:

hive.optimize.skewjoin:是否优化数据倾斜的 Join,对于倾斜的 Join 会开启新的 Map/Reduce Job 处理,默认值为false。

hive.skewjoin.key    倾斜键数目阈值,超过此值则判定为一个倾斜的 Join 查询。默认值为100000

2.1.2和mapjoin有关的优化:

hive.auto.convert.join:是否根据输入小表的大小,自动将 Reduce 端的 Common Join 转化为 Map Join,从而加快大表关联小表的 Join 速度。

hive.mapjoin.smalltable.filesize:输入表文件的mapjoin阈值,如果输入文件的大小小于该值,则试图将普通join转化为mapjoin,默认25MB;

上面的两个参数是自动启用mapjoin,也可以手动启动mapjoin。

2.1.3 和where有关的优化

由于join操作是在where操作之前执行,所以当你在执行join时,where条件并不能起到减少join数据的作用。

优化前:

select o.cid,c.id from order o
join customer c
on o.cid=c.id where o.dt='2013-12-12';


优化后:

select o.cid,c.id from (select cid from order where dt='2013-12-12') o
join customer c
on o.cid=c.id;


优化后会在map端通过where语句过滤掉一些数据,提高了效率

2.2 group by优化

hive.groupby.skewindata:group by操作是否允许数据倾斜,默认是false,当设置为true时,执行计划会生成两个map/reduce作业,第一个MR中会将map的结果随机分布到reduce中,达到负载均衡的目的来解决数据倾斜。

hive.groupby.mapaggr.checkinterval:map端做聚合时,group by 的key所允许的数据行数,超过该值则进行分拆,默认是100000;

2.3 count distinct优化

优化前:

select count(distinct id) from tablename;

在数据量大时,可以使用如下优化:

select count(1) from (selectdistinct id from tablename) tmp;

select count(1) from (select id from tablename group by id) tmp;

优化前查询只会启动一个job来完成,完成数据去重和计数时都只在一个reduce端(即便通过mapred.reduce.tasks设置reduce的数目为多个,但实际执行时仍然只有一个)进行,优化后会启动两个job来完成,同时可以通过mapred.reduce.tasks设定更多的reduce数目,所以适合在数据量很大的情况下使用,因为初始化一个job时花费的时间也会很长。

看一个更复杂的例子:

优化前:

select a,sum(b),count(distinct c),count(distinct d)
from test group by a;


优化后:

from (
select a,0 as b,c,null as d from test group by a,c
union all
select a,0 as b,null as c,d from test group by a,d
union all
select a,b,null as c,null as d from test
) tmp1 group by a;


3. Hive job优化

3.1 并行化执行

每个查询被Hive转化为多个阶段,有些阶段的关联性不大,则可以并行化执行,减少执行时间。

使用并行化执行前,需要配置以下参数:

hive.exec.parallel:hive的执行job是否并行执行,默认不开启false,在很多操作如join时,子查询之间并无关联可独立运行,这种情况下开启并行运算可以大大加速;

hvie.exec.parallel.thread.number:并行运算开启时,允许多少作业同时计算,默认是8;

3.2 本地化执行

使用本地化执行前,需要配置以下参数:

hive.exec.mode.local.auto:是否由hive决定自动在local模式下运行,默认是false。

配置了上面参数后,该job还必须满足以下条件,才能真正的使用本地模式:

1. job的输入数据大小必须小于参数

hive.exec.mode.local.auto.inputbytes.max(默认128MB)

2. job的map数必须小于参数:

hive.exec.mode.local.auto.tasks.max(默认4),我使用的hive版本为1.2.1,貌似已经取消了该配置

3. job的reduce数必须为0或1。

3.3 合并小文件

1. 合并输入小文件

set mapred.max.split.size=256000000;  #每个Map最大输入大小

set mapred.min.split.size.per.node=100000000; #一个节点上split的至少的大小 

set mapred.min.split.size.per.rack=100000000; #一个交换机下split的至少的大小

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;  #执行Map前进行小文件合并

2. 合并输出小文件

hive.merge.mapfiles:在只有map的作业结束时合并小文件,默认开启true;

hive.merge.mapredfiles:在一个map/reduce作业结束后合并小文件,默认不开启false;

hive.merge.size.per.task: 合并后每个文件的大小,默认256000000

3.4 JVM重利用

Hadoop中有个参数是mapred.job.reuse.jvm.num.tasks(hadoop2 为:mapreduce.job.jvm.numtasks),默认是1,表示一个JVM上最多可以顺序执行的task数目(属于同一个Job)是1。也就是说一个task启一个JVM。

适当地增大该值对于有较多task的job是分厂有意义的,但是也有个缺点就是:开启JVM重用将会一直占用使用到的task插槽,以便进行重用,直到任务完成后才能释放。如果某个“不平衡“的job中有几个reduce task 执行的时间要比其他reduce task消耗的时间多得多的话,那么保留的插槽就会一直空闲着却无法被其他的job使用,直到所有的task都结束了才会释放。

3.5 压缩数据

1.中间结果压缩

中间结果压缩就是处理hive查询的多个job之间的数据,对于中间压缩,最好选择一个节省CPU耗时的压缩方式。

hive.exec.compress.intermediate:决定查询的中间 map/reduce job (中间 stage)的输出是否为压缩格式。 

hive.intermediate.compression.codec:中间 map/reduce job 的压缩编解码器的类名(一个压缩编解码器可能包含多种压缩类型),该值可能在程序中被自动设置。           

hive.intermediate.compression.type:中间 map/reduce job 的压缩类型,如 "BLOCK""RECORD"。  

我自己使用的是hive1.2.1版本,但是没有找到hive.intermediate.compression.codec和hive.intermediate.compression.type这两个配置项,如果有朋友跟我的不一样,可以跟我说下。

2.最终结果压缩

hive.exec.compress.output:决定查询中最后一个 map/reduce job 的输出是否为压缩格式。   

mapred.output.compression.codec:最后结果的压缩编解码器的类名

mapred.output.compression.type:最后结果的压缩类型
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Hive优化