分享

hive分区知识整理

xuanxufeng 2016-8-23 19:52:31 发表于 总结型 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 1 21363
问题导读
1.hive如何创建表和分区?
2.如何加载数据?
3.hive默认是静态分区,还是动态分区?
4.动态分区如何实现?





hive分区还是比较重要的。这里整理下关于hive分区的一些知识。

1.hive分区

Hive创建表和分区
CREATE EXTERNAL TABLE IF NOT EXISTS data_zh(
ROWKEY STRING,
STATION INT,
YEAR INT,
MONTH INT,
DAY INT,
HOUR INT,
MINUTE INT,
)
PARTITIONED BY (AGE INT) 指定分区(此列并没真正存储列,也就是不存于你的数据中。但是如果你的数据从Oracle按年份导出,按照年份分区,把每一年数据放到age对应的目录下)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ‘,’ 字段分隔符
LINES TERMINATED BY ‘\n’ 行分隔符
STORED AS TEXTFILE; 作为文本存储


Hive加载数据到表中加载数据
LOAD DATA INPATH ‘/data/’ OVERWRITE INTO TABLE data_zh; #加载某个目录下所有数据,存在分区数据不能这样加载


分区加载数据
创建分区
ALTER TABLE data_zhp ADD PARTITION(AGE= 1998)
加载数据
LOAD DATA INPATH ‘/data/1998.txt’ INTO TABLE data_zhp PARTITION(YEAR=1998);
指定分区目录
LOCATION ‘ /hiveuser/hive/warehouse/data_zh.db/data_zh/2012.txt’;(指定分区所在位置)
加载数据到指定分区,分区表加载方法
下面为将现有表,修改为分区表。注意创建分区的时候未指定分区表,不能创建分区。需要新建表哥,用动态分区导入数据,动态分区数量有限。参考Programming Hive记得最大上限应该是10000


Hive修改现有表添加分区添加分区
ALTER TABLE data_zh ADD IF NOT EXISTS
PARTITION (year = 1998) LOCATION ‘/hiveuser/hive/warehouse/data_zh.db/data_zh/1998.txt’


删除分区
ALTER TABLE data_zhp DROP IF EXISTS PARTITION(year =1998);


修改现有表添加分区
创建分区表
CREATE EXTERNAL TABLE IF NOT EXISTS data_zhp(
ROWKEY STRING,
STATION INT,
MONTH INT,
DAY INT,
HOUR INT,
MINUTE INT,
)
PARTITIONED BY (YEAR INT)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ‘,’
LINES TERMINATED BY ‘\n’
STORED AS TEXTFILE;


动态分区指令
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
#set hive.enforce.bucketing = true;


未分区表数据导入分区表
insert overwrite table data_zhp partition (YEAR,MONTH) select * from data_zh;


2.hive动态分区与静态分区


HIVE分区,实际上是通过一个路径来标识的,而不是在物理数据中。比如每天的数据,可能分区是pt=20121023这样,那么路径中它就会变成:/hdfs/path/pt=20121023/data_files。通过路径来标识的好处是,如果我们需要取特定分区的数据,只需要把这个路径下的数据取出来就可以了,不用扫描全部的数据。

HIVE默认是静态分区。但是有时候可能需要动态创建不同的分区,比如商品信息,我想根据它是否在线分成两个分区,这样后续如果要取在线商品,就只需要从在线的分区获取即可。动态分区可以通过下面的设置来打开:

[mw_shl_code=bash,true]
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;[/mw_shl_code]

然后代码里就可以这么写:

[mw_shl_code=bash,true]
insert overwrite table tbl_name partition(pt, if_online)
select field1, field2, ..., pt, if_online
from tbl
where xxx;[/mw_shl_code]

注意输入字段的最后面必须是动态分区字段。

看一下与静态分区写法的区别:

[mw_shl_code=bash,true]
insert overwrite table tbl_name partition(pt=20121023, if_online=1)
select field1, field2, ..., fieldn
from tbl
where xxx;[/mw_shl_code]

动态分区与静态分区还有一个细微的差别是,静态分区一 定会创建分区,不管SELECT语句的结果有没有数据。而动态分区,只有在SELECT结果的记录数>0的时候,才会创建分区。因此在不同的业务场景下,可能会选择不同的方案。

另外使用动态分区时需要注意的比较重要的一点是,动态分区会为每一个分区分配reduce数。比如说你在脚本上面写了:set mapred.reduce.tasks=100;

并且有两个分区:pt, if_online。如果结果集中pt=20121023,if_online=0/1,那么它就会为pt=20121023/if_online=0,pt=20121023/if_online=1各分配100个reduce。也就是说,namenode会同时处理200个文件的写操作。这在分区值很多的情况下,会成为一个灾难,容易直接把namenode给搞挂掉,是非常危险的。因此使用动态分区时,一定要清楚地知道产生的动态分区值,并且合理地设置reduce数量。




已有(1)人评论

跳转到指定楼层
xingoo 发表于 2016-8-24 14:43:40
总结的不错,点个赞! 另外,分区多了,也会对map reduce的任务造成一定的影响...
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条