hive 分桶优化实例

项目进行到快要上线了,一直有一个问题存在。就是整个项目做的客户画像指标过于复杂,导致短时间内无法对指标分析,编出增量的SQL代码,所以导致每天都要全量跑所有的客户画像指标,简化下就是每日跑全量,整个全量跑批在17个节点上大概三个小时,还能接受。。。然后我们又需要将每日最终的三张全量画像导入hbase和solr,hbase大概每分钟一百万,solr大概每分钟一千万。这个就难以接受了。因为hbase每分钟才一百万(没有做bulkload,使用hive自带的bulkload没有生效,以后再研究),整个数据量是在10亿左右,这个时间算下来难以想象。。。

1、最原始的流程

整个计算都是基于全量,导入HBASE也都是全量数据,大概是要每天导入10亿左右。
同事在使用华为平台的bulkload,大概能做到30分钟导入4个亿数据,集群大概四十台。但是我们使用CDH,没法使用华为的工具,最后采用hive原生的bulkload,集群只有二十台,原以为会很快,结果导入速度只达到了每分钟100万。

参考连接:hive原生bulkload到hbase

使用bulkload方案,肯定是最快,但是应该是cdh使用的hive版本低,达不到那个连接的效果,以后再试试其他方式
2、变更hbase导入为增量导入

由于我们使用的bulkload没法生效,时间又紧张。所以反复思考,突然灵光闪现。。。今天的增量数据其实不一定是前面的计算逻辑必须改成增量计算,只需比较两天的全量数据差异,即可拿到今日的增量。虽然前面的计算逻辑依然慢,但导入hbase的速度提高N倍,毕竟一天增量变化最多100万以内。
先举例说明如何对比今日全量表A和昨日全量B,得出数据差异。假设字段只有两个f1和f2。,对比sql非常简单:

insert into table t_increment
select A.*
from A
where not exists (
select 1
from B
where CONCAT(A.f1,A.f2) = CONCAT(B.f1,B.f2)
);

执行测试后,这里A,B两表都各有14亿左右的数据,发现对比速度异常缓慢。预估得要几个小时吧。
通过查看执行计划,发现hive在map阶段会对两表对比字段进行排序,然后进行reduce。

原以为这条路走不通,后来又想到not exists其实是做的outer join等实现的,所以利用分桶优化join的想法自然就冒出来。
首先在A表和B表加一个字段叫COMPARE_DIFF_KEY,然后在插入两表的时候就先把两个字段contact插入到COMPARE_DIFF_KEY中。然后在使用这一个字段关联,14亿的数据8-15分钟就能比对出结果。只是分桶建表会多花十分钟左右。

512桶执行计划

1024桶执行计划

a、建表语句

--这两个环境变量必须设置,不然分桶排序不会生效。
set hive.enforce.bucketing = true;
set hive.enforce.sorting=true;
create table A(
COMPARE_DIFF_KEY string,
f1 string,
f2 string
)
CLUSTERED BY(COMPARE_DIFF_KEY) SORTED BY (COMPARE_DIFF_KEY) INTO 1024 BUCKETS
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS PARQUET;

create table B(
COMPARE_DIFF_KEY string,
f1 string,
f2 string
)
CLUSTERED BY(COMPARE_DIFF_KEY) SORTED BY (COMPARE_DIFF_KEY) INTO 1024 BUCKETS
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS PARQUET;

b、插入数据的时候提前concat,做好比较键.拼出来的字段会很长,你也可以在concat后使用md5

insert into table A
select concat(x.f1,x.f2),x.* from x;

insert into table B
select concat(x.f1,x.f2),x.* from x;

c、执行比对:

insert into table t_increment
select A.*
from A
where not exists (
select 1
from B
where A.COMPARE_DIFF_KEY = B.COMPARE_DIFF_KEY
)

不幸的是,在执行的过程又会报错:

查看表情况,确实是num buchket为2048,但是numfiles为4096。这个报错只是说明不能使用map join,只能采用reducejoin。所以只能禁用掉map join,虽然我觉得性能会下降,但是相比原来还是会快很快。

set hive.auto.convert.sortmerge.join=false;
set hive.optimize.bucketmapjoin = false;
set hive.optimize.bucketmapjoin.sortedmerge = false;

3、以后的两个目标

发表评论

电子邮件地址不会被公开。 必填项已用*标注