Hive静态分区和动态分区

需要建立一个备份带分区的数据表,拷贝时若采用静态分区方式需要写 N 行语句,因此可以使用动态分区,节省大量时间。

hive 的分区方式:由于 Hive 实际是存储在 HDFS 上的抽象,Hive 的一个分区名对应一个目录名,子分区名就是子目录名,并不是一个实际字段。

一)hive 中支持两种类型的分区:

  • 静态分区 SP(static partition)
  • 动态分区 DP(dynamic partition)

静态分区与动态分区的主要区别在于静态分区是手动指定,而动态分区是通过数据来进行判断。详细来说,静态分区的列实在编译时期,通过用户传递来决定的;动态分区只有在 SQL 执行时才能决定。

二)实战演示如何在 hive 中使用动态分区

1、创建一张分区表,包含两个分区 dt 和 ht 表示日期和小时

CREATE TABLE partition_table001
(
name STRING,
ip STRING
)
PARTITIONED BY (dt STRING, ht STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t";

 2、启用 hive 动态分区,只需要在 hive 会话中设置两个参数:

set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;

注意,动态分区不允许主分区采用动态列而副分区采用静态列,这样将导致所有的主分区都要创建副分区静态列所定义的分区。hive.exec.dynamic.partition.mode它的默认值是 strick,即不允许分区列全部是动态的,这是为了防止用户有可能原意是只在子分区内进行动态建分区,但是由于疏忽忘记为主分区列指定值了,这将导致一个 dml 语句在短时间内创建大量的新的分区(对应大量新的文件夹),对系统性能带来影响。

3、把 partition_table001 表某个日期分区下的数据 load 到目标表 partition_table002

使用静态分区时,必须指定分区的值,如:

create table if not exists partition_table002 like partition_table001;
insert overwrite table partition_table002 partition (dt='20150617', ht='00') select name, ip from partition_table001 where dt='20150617' and ht='00';

此时我们发现一个问题,如果希望插入每天 24 小时的数据,则需要执行 24 次上面的语句。而动态分区会根据 select 出的结果自动判断数据改 load 到哪个分区中去。

4、使用动态分区

insert overwrite table partition_table002 partition (dt, ht) select * from partition_table001 where dt='20150617';

hive 先获取 select 的最后两个位置的 dt 和 ht 参数值,然后将这两个值填写到 insert 语句 partition 中的两个 dt 和 ht 变量中,即动态分区是通过位置来对应分区值的。原始表 select 出来的值和输出 partition 的值的关系仅仅是通过位置来确定的,和名字并没有关系,比如这里 dt 和 st 的名称完全没有关系。
只需要一句 SQL 即可把 20150617 下的 24 个 ht 分区插到了新表中。

三)静态分区和动态分区可以混合使用
1、全部 DP

INSERT OVERWRITE TABLE T PARTITION (ds, hr)
SELECT key, value, ds, hr FROM srcpart WHERE ds is not null and hr>10;

2、DP/SP 结合

INSERT OVERWRITE TABLE T PARTITION (ds='2010-03-03', hr)
SELECT key, value, /*ds,*/ hr FROM srcpart WHERE ds is not null and hr>10;

3、当 SP 是 DP 的子分区时,以下 DML 会报错,因为分区顺序决定了 HDFS 中目录的继承关系,这点是无法改变的

-- throw an exception
INSERT OVERWRITE TABLE T PARTITION (ds, hr = 11)
SELECT key, value, ds/*, hr*/ FROM srcpart WHERE ds is not null and hr=11;

4、多张表插入

FROM S
INSERT OVERWRITE TABLE T PARTITION (ds='2010-03-03', hr)
SELECT key, value, ds, hr FROM srcpart WHERE ds is not null and hr>10
INSERT OVERWRITE TABLE R PARTITION (ds='2010-03-03, hr=12)
SELECT key, value, ds, hr from srcpart where ds is not null and hr = 12;

5、CTAS,(CREATE-AS 语句),DP 与 SP 下的 CTAS 语法稍有不同,因为目标表的 schema 无法完全的从 select 语句传递过去。这时需要在 create 语句中指定 partition 列

CREATE TABLE T (key int, value string) PARTITIONED BY (ds string, hr int) AS
SELECT key, value, ds, hr+1 hr1 FROM srcpart WHERE ds is not null and hr>10;

6、上面展示了 DP 下的 CTAS 用法,如果希望在 partition 列上加一些自己的常量,可以这样做

CREATE TABLE T (key int, value string) PARTITIONED BY (ds string, hr int) AS
SELECT key, value, "2010-03-03", hr+1 hr1 FROM srcpart WHERE ds is not null and hr>10;

四)小结:

通过上面的案例,我们能够发现使用 hive 中的动态分区特性的最佳实践:对于那些存在很大数量的二级分区的表,使用动态分区可以非常智能的加载表,而在动静结合使用时需要注意静态分区值必须在动态分区值的前面

转载自:https://www.deeplearn.me/1536.html

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

微信扫一扫

微信扫一扫

微信扫一扫,分享到朋友圈

Hive静态分区和动态分区