HIVE实战处理(四)大数据量导入hive动态分区异常处理

一、分区表的场景

分区是在处理大型事实表时常用的方法。
分区的好处在于缩小查询扫描范围,从而提高速度。
分区分为两种:静态分区static partition和动态分区dynamic partition。
静态分区和动态分区的区别在于导入数据时,是手动输入分区名称,还是通过数据来判断数据分区。对于大数据批量导入来说,显然采用动态分区更为简单方便。

1、整个数据流程
迁移过程中的hbase历史数据导入phoenix问题,借助hive2phoenix的方法,方案是把hbase的数据分批导入到指定NAS路径,之后创建hive的外部表,根据指定的分隔符创建。
如果数据文件过大建议压缩存储到NAS,linux自带支持的压缩格式是gzip,bzip2。具体的见:
HIVE实战处理(三)hive的压缩格式以及压缩文件导入hive实战

1)、创建从nas文件映射的外部表(分割符和nas文件保持一致)
create external table temp.tmp_hive1
(ststis_day string,

)row format delimited fields terminated by ‘|’
;

2)、因为phoenix的表的话是要求有分区,所以hive这边也一样保持分区数据
首先,新建一张我们需要的分区以后的表
create table temp.temp_kefu_user_visit_1h_delta_hourly
(statis_day string,

) partitioned by (dt string,hour string)

3)、导入hive1表的数据到分区表
然后,我们修改一下hive的默认设置以支持动态分区:

#参数详解:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
#这两个参数仅在你仅使用动态分区字段做分区索引时。
#然后用hive的insert命令进行插入操作。注意,除了所有列外,需要将分区的动态字段跟在后面。
二、动态分区的异常

Caused by: org.apache.hadoop.hive.ql.metadata.HiveFatalException: [Error 20004]: Fatal error occurred when node tried to create too many dynamic partitions.
The maximum number of dynamic partitions is controlled by hive.exec.max.dynamic.partitions and hive.exec.max.dynamic.partitions.pernode.
Maximum was set to: 1000

导入动态分区的数据量太大,超过了最大的分区数设置,所以需要增加提示的参数值。

#整个执行程序
set mapreduce.job.name=temp.temp_kefu_user_visit_1h_delta_hourly_partition_0_again;
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
insert overwrite table temp.temp_kefu_user_visit_1h_delta_hourly_partition_0 partition (dt,hour) 
select 
statis_day 
,search_time   
,serv_number   
,prov_id       
,region_id     
,node_id       
,sup_node_id   
,url_detail    
,sup_url_detail
,client_id     
,chn_id        
,chn_id_source 
,cp_id         
,cp_name       
,node_type     
,net_type      
,term_type     
,gate_ip       
,session_id    
,page_id       
,term_prod_id  
,business_id   
,sub_busi_id   
,virt_busi_id  
,client_code   
,rowkey 
,case when nvl(statis_day, '') = '' then '2018' else statis_day end as dt
,case when nvl(substr(search_time,9,2), '') = '' then '00' else substr(search_time,9,2) end as hour
from temp.temp_kefu_user_visit_1h_delta_hourly;

对于数据量小的原始hive表来说,开启动态分区使用默认参数配置应该是可以插入成功的,
=数据量大或者上面执行失败的话往下看。=

三、参数设置以及代码优化

在hive中,有时候会希望根据输入的key,把结果自动输出到不同的目录中,这可以通过动态分区来实现,就是把每一个key当作一个分区,这时候要用distribute by 来限制生成的文件个数。
代码示例如下:

但是这还不够,在动态分区有可能很大的情况下,还需要其他的调整:

 #参数指的是每个节点上能够生成的最大分区,这个在最坏情况下应该是跟最大分区一样的值
hive.exec.dynamic.partitions.pernode
 #参数指的是总共的最大的动态分区数
hive.exec.dynamic.partitions.partitions
#参数指的是能够创建的最多文件数(分区一多,文件必然就多了...)
hive.exec.max.created.files 
#最后要注意的是select语句中要把distribute的key也select出来
  • 正确的数据代码如下:
set mapreduce.job.name=temp.temp_kefu_user_visit_1h_delta_hourly_partition_0_two;
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
#这两个参数仅在你仅使用动态分区字段做分区索引时。
#然后用hive的insert命令进行插入操作。注意,除了所有列外,需要将分区的动态字段跟在后面。
set hive.exec.max.dynamic.partitions.pernode=600000;
set hive.exec.max.dynamic.partitions=6000000;
set hive.exec.max.created.files=6000000;

insert overwrite table temp.temp_kefu_user_visit_1h_delta_hourly_partition_0 partition (dt,hour) 
select
statis_day 
,search_time   
,serv_number   
,prov_id       
,region_id     
,node_id       
,sup_node_id   
,url_detail    
,sup_url_detail
,client_id     
,chn_id        
,chn_id_source 
,cp_id         
,cp_name       
,node_type     
,net_type      
,term_type     
,gate_ip       
,session_id    
,page_id       
,term_prod_id  
,business_id   
,sub_busi_id   
,virt_busi_id  
,client_code   
,rowkey
,dt
,hour
from
(select 
statis_day 
,search_time   
,serv_number   
,prov_id       
,region_id     
,node_id       
,sup_node_id   
,url_detail    
,sup_url_detail
,client_id     
,chn_id        
,chn_id_source 
,cp_id         
,cp_name       
,node_type     
,net_type      
,term_type     
,gate_ip       
,session_id    
,page_id       
,term_prod_id  
,business_id   
,sub_busi_id   
,virt_busi_id  
,client_code   
,rowkey 
,case when nvl(statis_day, '') = '' then '2018' else statis_day end as dt
#动态分区的字段支持函数操作。我们得到了一张分区后的hive大表。

,case when nvl(substr(search_time,9,2), '') = '' then '00' else substr(search_time,9,2) end as hour
from temp.temp_kefu_user_visit_1h_delta_hourly
) t
distribute by dt,hour

;

整个map执行很快,在执行过程会启动1个map,但是很多reducer,这是distribute的效果,会根据分区的key进行划分多个reduce进行计算。
最后数据计算完成这部分耗时不长,stage-0 Starting task [Stage-0:MOVE] in serial mode,计算之后的数要移动到分区表所在的hdfs的目录下,这个因为文件的和reducer的个数一样很多,所以在移动过程中耗时比较长,需要耐心等待最后程序执行完成。

INFO  : Starting Job = job_1561342945833_12383421, Tracking URL = http://ddp-nn-01.cmdmp.com:8088/proxy/application_1561342945833_12383421/
INFO  : Kill Command = /opt/cloudera/parcels/CDH-5.10.0-1.cdh5.10.0.p0.41/lib/hadoop/bin/hadoop job  -kill job_1561342945833_12383421
INFO  : Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 20000
。。。。。。。
NFO  : 2020-05-07 16:44:12,109 Stage-1 map = 100%,  reduce = 96%, Cumulative CPU 39204.32 sec
INFO  : 2020-05-07 16:44:16,612 Stage-1 map = 100%,  reduce = 97%, Cumulative CPU 39608.4 sec
INFO  : 2020-05-07 16:44:21,157 Stage-1 map = 100%,  reduce = 98%, Cumulative CPU 39932.05 sec
INFO  : 2020-05-07 16:44:24,536 Stage-1 map = 100%,  reduce = 99%, Cumulative CPU 40408.81 sec
INFO  : 2020-05-07 16:44:31,246 Stage-1 map = 100%,  reduce = 100%, Cumulative CPU 40889.07 sec
INFO  : MapReduce Total cumulative CPU time: 0 days 11 hours 21 minutes 29 seconds 70 msec
INFO  : Ended Job = job_1561342945833_12383421
INFO  : Starting task [Stage-0:MOVE] in serial mode
INFO  : Loading data to table temp.temp_kefu_user_visit_1h_delta_hourly_partition_0 partition (dt=null, hour=null) from
分区表的hdfs的根目录/temp.db/temp_kefu_user_visit_1h_delta_hourly_partition_0/.hive-staging_hive_2020-05-07_16-35-45_383_5179510197282700947-417785/-ext-10000

在这里插入图片描述
最后参考:hive官网

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值