一:简介
分区表就是根据指定字段的值进行分类、分组,字段值相同的分为一类然后存储在一个单独的HDFS文件中,多个类就存储在多个文件中。原本存储在一个文件中的数据现在存储在多个文件中,查询数据时只需要知道数据在哪个类别中然后直接去对应类对应的文件中去查询就好,这样只需扫描这一个类别的文件而不需要扫描所有文件,这样提高了查询效率。
分区表就是对文件进行水平分割,对数据分门别类的分开存储。
分区表有两种:
- 静态分区: 必须手动显式的添加需要分区的字段值, 分类的值有多少个就要添加多少次 (alter table add partition)。静态分区适合分区字段的值比较少的情况。
- 动态分区:创建表时只需指定要分区的字段名即可,不需要指定分区字段有哪些具体的值。动态分区适用于字段值相对比较多的情况。
二:静态分区
1. 创建表并通过partitioned by指定分区字段
分区字段和普通字段是一样的,需要指定 <字段名> <字段类型> [comment '字段注释']
,分区字段也会作为表的列。
hive> create database test;
hive> use test;
hive> create table tbl_user (id bigint,username string comment '用户名')
partitioned by (country string comment '国家', state string comment '地区')
row format delimited
fields terminated by ","
lines terminated by "\n"
stored as textfile;
查看表结构
hive> describe extended tbl_user;
hive> desc tbl_user;
创建表后HDFS:/data/hive/warehouse/test.db/
2. 添加分区
>hive alter table tbl_user add partition (country="China",state="Asia");
>hive alter table tbl_user add partition (country="Japan",state="Asia");
-- 显示分区
>hive show partitions tbl_user;
-- 删除分区
alter table tbl_user drop partition(country="China",state="Asia")
添加分区后hdfs中会有对应的分区目录,如果是多个分区则会具体再分出子目录。
3. 插入数据
echo "1,zhangsan,China,Asia\n2,lisi,China,Asia" > '/tmp/china.txt'
echo "3,wangwu,Japan,Asia\n4,liuliu,Japan,Asia" > '/tmp/japan.txt'
hive> load data local inpath '/tmp/china.txt' into table tbl_user partition (country = 'China', state= 'Asia');
hive> load data local inpath '/tmp/japan.txt' into table tbl_user partition (country = 'Japan', state= 'Asia');
-- 查询时使用分区字段作为条件加快查询速度
>hive select * from tbl_user where country='Japan';
三: 动态分区
动态分区默认是没有开启的,开启后默认是严格模式即至少有一个静态分区,也可以关闭严格模式。
1. 关闭严格分区模式
关闭严格模式可以在hive-site.xml文件中配置,也可以通过命令行临时配置。
<property>
<name>hive.exec.dynamic.partition</name>
<value>true</value>
</property>
<property>
<name>hive.exec.dynamic.partition.mode</name>
<value>nonstrict</value>
</property>
<property>
<name>hive.exec.max.dynamic.partitions</name>
<value>1000</value>
</property>
-- 非严格模式
hive> set hive.exec.dynamic.partition.mode=nonstrict;
-- 开启动态分区
hive> set hive.exec.dynamic.partition=true;
-- 最大动态分区数,默认1000
hive> set hive.exec.max.dynamic.partitions=99999;
2. 创建表
动态分区创建表和静态分区创建表是一样的,只需要指定需要分区的字段,分区字段可以是多个。
create table tbl_user_dy (id bigint,username string)
partitioned by (city string)
row format delimited
fields terminated by ","
lines terminated by "\n"
stored as textfile;
3. 插入数据
echo "1,zhangsan,shanghai\n2,lisi,beijing\n3,wangwu,shenzhen\n4,liuliu,shanghai" > '/tmp/user.txt'
注意:动态分区不能使用load data local inpath '/tmp/user.txt' into table tbl_user_dy partition(city);
进行加载数据, 否则会报FAILED: NullPointerException null
。解决办法是 先创建没有分区的表,将数据加载到没有分区的表,然后再将数据转移到动态分区表。
创建临时表不需要指定分区字段,将分区字段作为普通字段。
hive> create table tbl_user_tmp (id bigint,username string, city string)
row format delimited
fields terminated by ","
lines terminated by "\n"
stored as textfile;
-- 将数据加载到临时表中
hive> load data local inpath '/tmp/user.txt' into table tbl_user_tmp;
-- 将临时表中的数据插入到动态分区表中
hive> insert into table tbl_user_dy partition(city) select * from tbl_user_tmp;
自动分区会自动根据分区字段的值进行分区,这里根据城市city动态分区的,不需要手动显式添加分区值。