hive 调优 转发

1.列裁剪分区裁剪


尽可能早地过滤掉尽可能多的数据量,避免大量数据流入外层SQL。


列裁剪:在列存格式下(RCFile),列裁剪可以是我们只获取需要的列的数据,减少数据输入。


分区裁剪:分区在hive实质上是目录,分区裁剪可以方便直接地过滤掉大部分数据。


2.表分桶


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


桶的优势:


    1. 提高join效率。两个在相同列上划分了桶的表,可以使用到Map join以加快连接效率。由于两个表都进行了桶操作,那么只对保存相同哈希取余的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。


    2. 使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。


#设置环境变量
set hive.enforce.bucketing = true;


#1.建立分桶表
create table bucketed_user
  (dt   string,
   id   int,
   name string) 
clustered by (id) into 4 buckets ;
#2.插入数据
INSERT OVERWRITE TABLE bucketed_users SELECT * FROM users; 
#3.取样数据
SELECT * FROM bucketed_users TABLESAMPLE(BUCKET 1 OUT OF 4 ON id); 
(例如表bucket数为32,tablesample(bucket 3 out of 16),表示总共抽取(32/16=)2个bucket的数据,
分别为第3个bucket和第(3+16=)19个bucket的数据。)
3.map join


未优化:join操作默认在reduce端进行,map端到reduce端之间的shuffle过程会按照Key给reduce分发数据。当数据倾斜时部分reduce被分配过多的数据,而部分reduce分配到的数据量又极少,这种情况很可能导致任务的失败。


map join优化: mapjoin中小表被作为驱动表直接加载入内存,每个map都会拿另一个表的数据与内存中的小表数据做匹配,由于每个map处理的数据量大致相同,因此解决了数据倾斜问题。


select /*+ mapjoin(a)*/ a.id,b.col 
  from small_table a join big_table b 
  on a.id=b.id
4.sql负载均衡


    set hive.groupby.skewindata=true


    当数据group by出现倾斜时可进行负载均衡。当设定为 true,生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group ByKey 分布到 Reduce 中(这个过程相同Key的数据被分布到同一个 Reduce),最后完成最终的聚合操作。


set hive.groupby.skewindata=true
select a.id,count(*)
  from test_table a 
 group by a.id
5.合并小文件


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


解决小文件的问题可以从两个方向入手:


    1. 输入合并。即在Map前合并小文件


    2. 输出合并。即在输出结果的时候合并小文件


输入合并:


set mapred.max.split.size=256000000  #每个Map最大输入大小,决定合并后的文件数
set mapred.min.split.size.per.node=100000000  #单节点split最小大小,决定多个data node文件是否合并
set mapred.min.split.size.per.rack=100000000  #单交换机split最小大小,决定多交换机上文件是否合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat  #在map前进行小文件合并
输出合并:


set hive.merge.mapfiles=true  #在map-only job后合并文件,默认true
set hive.merge.mapredfiles=true  #在map-reduce job后合并文件,默认false
set hive.merge.size.per.task=128*1000*1000  #合并后每个文件的大小,默认256000000
set hive.merge.smallfiles.avgsize=16000000  #平均文件大小,是是否执行合并的阈值,默认16000000
6.sql并行


    在一些情况下,多个sql逻辑上可以并行执行,但是hive不会按照并行执行的方式去执行,这时我们需要手动设置参数来让它并行执行,以提升运行效率。比如:a与b表的join结果,与c与d表的join结果之间再做join,默认a join b与c join d不能并行。


set hive.exec.parallel=true; 
select t1.*,t2.* from 
    (select b.* from a join b on a.id=b.id) t1 join 
    (select d.* from c join d on a.id =b.id) t2
  on t1.x=t2.y
在资源充足的时候开放hive.exec.parallel会让那些存在并发job的sql运行得更快。


7.union all


在多个sql语句可以union的情况下,可以将几个sql union起来优化为一个job。


select * from 
  (select id,name from table_a a where opt_date='20160808' and loc='BeiJing'
   union all
   select id,name from table_a a where opt_date='20160816' and loc='TianJin'
   union all
   select id,name from table_a a where opt_date='20160818' and loc='ShenZhen')

你可能感兴趣的:(hive)