大数据开发主战场hive (企业hive应用)

hive在大数据套件中占很的地位,分享下个人经验。

1.在hive日常开发中,我们首先面对的就是hive的表和库,因此我要先了解库,表的命名规范和原则

如 dwd_whct_xmxx_m

第1部分为表数据仓库分层:可能取值为ods,dwd(dw明细层),dws(dw汇总层),ads(应用层)等。
第2部分为业务领域 可能为whct(文化传统),whcp文化产品等。
第3层为用户自定义标签 比如项目信息为xmxx,用户可以可以自己定义业务,项目和产品标签
第4层为时间标签:比如d为天,m为月,y为年,di为增量表,df为全量表。
ods:源头数据原封不动的抽取一遍,准备层。
dw:dwd(数据仓库明细层),dws(数据仓库汇总层)经过ods层数据经过etl清洗,转换,加载生成。
ads:应用层,各个业务方或部门基于dwd和dws建立的数据集市(DM),原则上asd层数据是基于dw层的,不能直接访问ods层,该层只包含部门或业务方自己关心的dwd和dws。
这是使用hive的第一步,没有好的命名规则,那最后会一片狼藉。
 
2.hsql运行原理
熟悉hive sql 在 hadoop 上 mapreduce的运行原理,不知道这些,很难优化sql,减少资源的浪费。如下:
1)select 数据  
eg :select  *  from tb_tbale where cloumn1 = '2019' and cloumn2 = 'hive'; 
执行select 语句时,hive只有map阶段,无shuffle和reduce。
map:该阶段会根据split个数开启几个map,每个map task会接收到一个split文件,于是每个map函数会逐行对输入的文件进行检测筛选出cloumn1为2019,cloumn2为hive的数据,保存在本地。
map的个数可以这样理解。如果文件为256M,hadoop2(每个块128)的话,会开启2个map。289M就会三个,要注意的是这些map都是并行执行的,当数据量特别大
的时候开启的map会越多,理论上还会并行执行,所以我们一定要养好习惯select数据的时候一定要加上where条件,避免盲目查询。
 
2)gruop by     
eg: select  cloumn1,count(*)  from tb_tbale  where cloumn2 = ‘hive’  group by cloumn1
map:分完片的文件会产生相应数量的map,每个map会逐行检测cloumn2是否为hive,如果是hive它会生成键值对<cloumn1,1>。
combine: 该操作发生在对应的文件中,也就是讲map分了几个,也就有几个combine,他会把map端产生的键值对相同的key对进行累加如<cloumn1,3>。
shuffle:该操作比较复杂,分为partition,sort,spill,copy,merge.最重要的就是分区和合并过程。
map生成的task会通过对每个键取hash值,使map task按照相同的键均匀分配到reduce上,这个过程就是分区,分配到同一个reduce上的task会经过合并过程
生成这样的键值对<cloumn1,{3,1}>>做完reduce task输入。
reduce:调用函数将他没累加即可,3+1=4
 
3)join
eg: select t1.cloumn1,t2.cloumn2 from (select cloumn1,cloumn3 from tb_table1)  t1 join (select cloumn2,cloumn3 from tb_table2)  t2 on t1.cloumn3= t2.cloumn;
会开启三个mapreduce任务。第一个会执行select cloumn1,cloumn3的操作,第2个会执行selec cloumn2,cloum3的操作,主要是第三个,会把第一个和第2个
的结果进行关联合并,然后输出。
split:jion的时候会把第一个mapreduce和第2个MapReduce任务的输出文件输入该次任务。首先会对前两个任务进行分片。hadoop大于128mb分一个片。
map:hadoop 集群根据spilt出来分结果开启相应个数的map task
shuffle:jion时,主要是分区操作,jion的列进行数据的重分布和分发过程,分区的类为cloumn3,于是所有的map task都根据cloumn3进行发布。相同jion知道就会
发生到同一个reducer上。
reduce:shuffle发送的cloumn1,cloumn3 ; cloum2,cloum3.就会根据cloum3 发送到 reduce task上。这个时候根据cloum3将他们的值变成一行,保留到本地输
处文件中
 
 
3.hive函数:
了解hive函数对我们数据分析等十分重要,常用日期函数如下:
日期函数:Date_add,datediff,to_date,from_unixtime,unix_timestamp
字符串函数:substr,concat,concat_ws,split,regexp_replace,get_json_object,trim,length
聚合函数:abs,ceil,floor,round,rand,pow
数字函数:count,max,min,avg,count distinct,sum,group_concat
窗口函数:Row_number,lead,lag,rank
其他函数:Coalesce,cast,decode explode
 
 
4.hive 简单优化:
1)对于group by引起的倾斜,只要设置下面的参数
set hive.map.aggr =ture
set hive.groupby.skewindata=true
此时hive数据倾斜时会发生负载均衡,生成的查询计划会有两个MapReduce job。第一个MapReduce job中,map输出结果聚合会随机分配到reduce中,每个reduce做部分均和操作并输出结果,这样处理结果是相同的groupbykey有可能被分布到不同的reduce中,所以达到了负载均衡的目的,第2个MapReduce job再根据预处理的数据结果按照groupbykey分布到reduce中,最后完成聚合操作。
2)对于count distinct的优化
在hive开发过程中应该小心使用count distinct,因为很可能出现性能问题,比如
select count(distinct name)from dwd_some_table;
此时因为要去重,hive会把map阶段的输出全部分配到一个reduce task 上,此时很容易发生性能问题,这样我们可以这样先group by 再count,减少distinct的使用。
select count(1) from (select name from dwd_some_table group by user) tmp;
3)对于join的优化最为常用,也很广泛,我给它分为如下几种:
大表join小表:
现实世界的28法则会把百分之八十的数据集中在百分之二十的用户上,数据倾斜很难不会发生,这时候大表join小表的时候可以使用mapjoin的方法来优化,
格式为/*+mapjoin(b,c,d),join个表,mapjoin的优化在map端进行join,不是像通常那样在reduce端按照join列来进行分发后在每个reduce任务节点进行join,不分发也就没有了倾斜问题。相反hive会把小表全量复制到每个map任务节点,然后map任务节点执行lookup小表便可。这样小表不可以太大,不然全量复制得不偿失。
参数hive.auto.convert.join.noconditionaltask.size 来确定是否为小表,默认为25M,最大不可以调节大于1G.
 
 
5.创建一个分区表,以 ds 为分区列:
create table invites (id int, name string) partitioned by (ds string) row format delimited fields terminated by 't' stored as textfile;
将数据添加到时间为 2013-08-16 这个分区中:
load data local inpath '/home/hadoop/Desktop/data.txt' overwrite into table invites partition (ds='2013-08-16');
从一个分区中查询数据:
select * from invites where ds ='2018-11-14';
往一个分区表的某一个分区中添加数据:
insert overwrite table invites partition (ds='2018-11-14') select id,max(name) from test group by id;
可以查看分区的具体情况,使用命令:
hadoop fs -ls /home/hadoop.hive/warehouse/invites
或者:
show partitions tablename;
 
6. 创建带桶的 table :
create table bucketed_user(id int,name string) clustered by (id) sorted by(name) into 4 buckets row format delimited fields terminated by '\t' stored as textfile;
首先,我们来看如何告诉Hive—个表应该被划分成桶。我们使用CLUSTERED BY 子句来指定划分桶所用的列和要划分的桶的个数
CREATE TABLE bucketed_user (id INT, name STRING)
CLUSTERED BY (id) INTO 4 BUCKETS;
桶中的数据可以根据一个或多个列另外进行排序。由于这样对每个桶的连接变成了高效的归并排序(merge-sort), 因此可以进一步提升map端连接的效率。以下语法声明一个表使其使用排序桶:
CREATE TABLE bucketed_users (id INT, name STRING)
CLUSTERED BY (id) SORTED BY (id ASC) INTO 4 BUCKETS;
 
 
7.hive动态分区
动态分区导入:
  set hive.exec.dynamic.partition=true;
  set hive.exec.dynamic.partition.mode=nonstrict;
 
  insert overwrite table user_log_p_action partition(p_action)
  select user_name
       ,action_type
       ,ip
       ,action_type as actiontype
  from user_action_log
  其中p_action是分区表的分区字段名称
  ,action_type as actiontype:必须要放在表正式字段的后面,按顺序这个位置往后是分区字段值,动态导入的过程就是根据分区字段值来分区的
 
 
 

猜你喜欢

转载自www.cnblogs.com/xiaodong520/p/10020860.html
今日推荐