Hive优化的基本方法

引言

今天被问到Hive的一些常规优化方法,发现自己居然没有这方面的记录,所以准备简单记录一下自己遇到的一些问题,供接触Hive的朋友参考。

概念

首先说一个老生常谈的但是很重要的问题,Hive不是数仓!!!Hive不是数仓!!!Hive不是数仓!!!重要的事情说三遍。
数仓是一个抽象的理论性的概念,Hive只是实现数仓建设的工具之一。它其实做了一件事情就是把sql解析转换成了MR并在hadoop集群上运行。虽然现在还有tez,spark等引擎

问题&解决办法

一 数据倾斜

基本上大伙应该都会遇到一个很蛋疼的问题,那就是数据倾斜,那么到底在什么情况下会造成数据倾斜?
第一:两个表关联的时候
第二:去重的时候
但是归根结底还是一个原因:某个key的值太多了,都跑到了一个reduce下面去执行。造成的结果就是其余的reduce早早的就完了,而这一个还在慢慢的跑。
下面就简单说一下我遇到数据倾斜的情况。

1 两表关联的时候关联键上有空值

这种情况个人遇到的不是很多,造成这种情况的主要原因是数据质量的问题。发生在流量统计侧的可能性比较大。
其解决办法就是用随机函数去填补这个空值
select *
  from a
  left join b
    on a.id=if(b.id is null,rand(100),b.id)

2 大小表关联

这种情况主要出现在事实表和维表关联的时候。维表数据量较少,而且事实表的维值分布不均匀
其解决办法就是使用 mapjoin,让小表优先加载到内存当中,在map端和事实表关联,省去了shuffle和reduce的计算过程。
set hive.auto.convert.join=true;
set hive.mapjoin.smalltable.filesize=25000000;
select *
  from a
  left join b
    on a.id=b.id

注:第一个参数是开启mapjoin,第二个是设置小表的阈值,默认是25M,若小表大于25M则不会走mapjoin。当然还有许多相关参数,可以自行百度

3 去重计算

这种情况主要出现 count(distinct)的情况下。但是不要完全否定distinct,在key值分布均匀的情况下,count(distinct)的效率还是不错的。这种情况的解决办法就是先group by 去重在count
select count(1)
   from (select id 
           from tbl1
          group id 
         ) a

4 SQL改写

SQL改写其实是比较常用的一种情况,其方法包括但不限于利用union all并开启并行,合理利用分析函数,distribute by + sort by等。其目的在于减少jon是
下面这个例子适用于两个表关联某个key中的值集中,但却用不了mapjoin的情况,改写的思路就是打散到更多的key去计算,然后再合并。
比如:
select xxxx
  from tbl a
  join tbl1 b
    on a.id=b.id
可以改写为
select split(a.id,'_')[1],sum(xxx)
  from (select xxxxx
          from tbl a
          join tbl1 b
            on concat(rand(),'_',a.id)=concat(rand(10),'_',a.id
       ) a
 group by split(a.id,'_')[1]

5 参数设置

同SQL改写一样,这个涵盖的范畴非常广,这里就不一一举例说明了,只是把自己用过的一些参数以及相应的理解说一下,如果有说的不对的地方,欢迎指正。
--开启map端聚合,这样会在map端进行一部分计算,减少网络传输的量
set hive.map.aggr=true;

--开启并行
set hive.exec.parallel=true

--开启自动优化数据倾斜,个人认为跟我sql改写的例子类似,会由一个job专为两个job
set hive.optimize.skewjoin=true
--每个Map最大输入值,决定合并后的文件数
set mapred.max.split.size=256000000;

--一个节点上split的值 ,决定多个数据节点上的文件是否合并
set mapred.min.split.size.per.node=256000000;

--一个交换机下split的值的大小,决定多个交换机上的文件是否合并
set mapred.min.split.size.per.rack=256000000;

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

--关闭推测执行
set mapred.map.tasks.speculative.execution=false;
set mapred.reduce.tasks.speculative.execution=false;
set hive.mapred.reduce.tasks.speculative.execution=false;

总结

可能有的朋友会说,一个好的模型根本不用在SQL写法上考虑这么多的事情,但是我想说,需求是无耻的,我不认为有完美模型的存在,在我们日常工作当中,SQL的占比其实是非常大的,所以希望能给用到的朋友带来帮助。

你可能感兴趣的:(hadoop,优化,hive,sql,数据技术)