您的位置:首页 > 其它

hive常用优化方式

2016-08-02 00:00 169 查看
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')
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息