hive静态分区和动态分区的详解

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

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

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

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

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

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

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

hive> create table part1_t1(
    > name string,
    > ip string
    > )
    > partitioned by (dt string,ht string)
    > row format
    > row format delimited fields terminated by ' '
    > ;
OK

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

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

3、把part1_t1 表示某个日期分区下的数据load到目标表 part1_t2使用静态分区时必须 指定分区,如:

create table if not exists part1_t2 like part1_t1;

insert table part1_t2 partition (dt='20190506',ht='00') select name,ip from part1_t1 where dt='20150506' and ht='00';

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

4、使用动态分区

只需要一句hql即可包20150506下的24个ht分区插入新表中

insert table part1_t1 partition(dt,ht) select * from 
part1_t1 where dt='20150506';

过程说明:

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

三、静态分区和动态分区可以混合使用

1、only动态分区
insert table1 partition (dt,ht) select key,value form table2 [where ...]
2、动态分区和静态分区结合
insert table1 partition (dt='20160507',ht) select key value from table2 [where..]
注意:当静态分区时动态分区的子分区的时候,以下的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;

四、hive的严格模式

1、配置信息
<property>
  <name>hive.mapred.mode</name>
  <value>nonstrict</value>
  <description>
      The mode in which the Hive operations are being performed. 
      In strict mode, some risky queries are not allowed to run. They include:
        Cartesian Product.
        No partition being picked up for a query.
        Comparing bigints and strings.
        Comparing bigints and doubles.
        Orderby without limit.
  </description>
</property>
严格模式阻挡5类查询:
1、笛卡尔积
set hive.mapred.mode=strict;
select
*
from dy_part1 d1
join dy_part2 d2
;

2、分区表没有分区字段过滤
set hive.mapred.mode=strict;
select
*
from dy_part1 d1
where d1.dt='2019-09-09'
;

不行
select
*
from dy_part1 d1
where d1.id > 2
;

select
*
from dy_part2 d2
where d2.year >= 2019
;

3、order by不带limit查询
select
*
from log3
order by id desc
;

4、(bigint和string比较)Comparing bigints and strings.

5、(bigint和double比较)Comparing bigints and doubles.