hive优化

1、大多数情况下查询会出发一个MapReduce任务(job)。hive中对某些情况的查询可以不必使用MapReduce,也就是所谓的本地模式。

select * from employee;

这种情况下,hive可以简单的读取employee对应的存储目录下的文件,然后格式化后的内容到控制台。

对于where语句汇总过滤条件只是分区字段这种情况(无论是否使用limit),也是无需MapReduce过程的。

select * from employee where country= “US” and state = “CA” limit 100;

set hive.exec.mode.local.auto=true

2、关于浮点数的比较

如浮点数0.2,FLOAT类型是0.2000001,DOUBLE类型是0.200000000001,FLOAT通过hive转换成DOUBLE是0.200000100000

3、join优化

hive执行多表join操作时,会将前面的表缓存起来,然后扫描最后那个表进行计算。因此,在使用join时应保持表的大小从左到右依次增加。

select /*+streamtable(s)*/ s.ymd,d.dividend from stocks s join dividends d on s.ymd = d.ymd where s.symbol='aapl';

4、outer join

select s.ymd,s.symbol,d.dividend 

  from s left outer join d on s.ymd=d.ymd

  where s.symbol = "appl" and d.exchange="nasdq";

与预期的结果可能不一样,会过滤掉null值。因为where语句是在join之后执行。

select s.ymd,s.symbol,d.dividend 

  from s left outer join d on s.ymd=d.ymd

  on s.ymd=d.ymd and s.symbol = "appl" and d.exchange="nasdq";

对于外连接是不可用的。过滤条件并不执行。(hive wiki上说是可以的,实际执行并不可行)针对内连接是可行的。

若想达到预期,可使用嵌套select语句。

select s1.ymd,s1.symbol,d1.dividend from

  (select * from s where s.symbol = "appl")s1

  left outer join

  (select * from d where d.exchange="nasdq") d1

  on s.ymd=d.ymd

5、left semi-join

hive 不支持以下查询

select s.ymd, from s where s.ymd in

  (select d.ymd from d);

但是可以使用left semi join实现同样的目的

select s.ymd from s left semi join d on s.ymd = d.ymd;

此时,select和where语句中不能引用到右边表中的字段。

 

6、笛卡尔积join

与其他链接类型不同,笛卡尔积不是并行执行的,而且使用MapReduce计算架构的话,任何方式都无法进行优化。如果hive.mapred.mode的值是strict的话,会阻止用户执行笛卡尔积查询。

7、order by和sort by

order by 会对查询结果集执行一个全局排序,如果数据量大会消耗更多时间。

sort by 会在每个reducer中对数据进行排序,保证每个reducer的输出结果都是有序的,可以提高后续的全局排序效率。

8、同一份数据多种处理

以下查询都会从源表history表读取数据,然后倒入到2个不同的表中

insert overwrite sales select* from history where action=“purchase”

insert overwrite sales select* from history where action=“returned”

这样做的操作会导致执行效率低。下面这个方法同样可以达到该效果,却只需扫描history 表一次

from history 

  insert overwrite sales select * where action=“purchase”

  insert overwrite sales select * where action=“returned”;

9、并行执行

hive会将一个查询转化成一个或多个阶段,可以是MapReduce阶段,抽样阶段,合并阶段,limit阶段,默认情况下hive一次只会执行一个阶段。不过有时这些阶段并非完全相互依赖,那就可以并行执行,缩短整个job的执行时间。

需要设置hive.exec.parallel的值为true

10、严格模式

hive。mapred。mode的值为strict可以禁止3中类型的查询。

  1、对于分区表,where语句中不包含分区过滤条件。

  2、order by语句的查询,需要强制增加limit字段

  3、限制笛卡尔积的查询

10、动态分区调整

严格模式下要求至少有一个分区是静态的。

 

11、是否合并小文件

hive.merge.mapredfiles =true

hive.merge.mapfiles=true

当Hive输入由很多个小文件组成,由于每个小文件都会启动一个map任务,如果文件过小,以至于map任务启动和初始化的时间大于逻辑处理的时间,会造成资源浪费,甚至OOM。

 Map输入合并小文件
对应参数:
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前进行小文件合并

在开启了org.apache.hadoop.hive.ql.io.CombineHiveInputFormat后,一个data node节点上多个小文件会进行合并,合并文件数由mapred.max.split.size限制的大小决定。
mapred.min.split.size.per.node决定了多个data node上的文件是否需要合并
mapred.min.split.size.per.rack决定了多个交换机上的文件是否需要合并

输出合并
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

 

 

posted @ 2018-03-01 00:06  walkshadow  阅读(147)  评论(0)    收藏  举报