1 、什么是分区表
一个表按照某个或某些字段进行分区的表
2、为什么要用分区表
如果一个hive表没有分区,在查询数据的时候,会进行全表扫描的动作,非常的耗费资源和时间。使用分区表可以只查询指定分区下的数据,大大减少了查询的时间。
3、建分区表
create table order(
order_num string,
order_time string
) partitioned by(order_month string)
row format delimited fields terminated by '\t';
这里建一个订单表,里面包含两个字段,一个订单编号,一个订单发生时间。然后是以订单发生的月份字段作为分区。我们往里面load些数据,需在后面添加分区信息
load data local inpath '/home/hadoop/data/order.txt' into table order partition (order_month='2018-01');
然后查询下数据
可以看到,查询出来的数据多了一列,这列就是分区数据。我们知道,hive表的数据是存在HDFS之上的,分区也是HDFS之上的一个文件夹。我们查看下HDFS
可以看到,在文件夹order之下,有个文件夹order_month=2018-01,这就是order表的分区信息,下面就是存储的具体数据。
如果分区就是在HDFS上新建分区的文件夹,那么我们可不可以直接在文件夹order下面直接新建一个新的分区文件呢,我们来试试
如图所示,我们在order表下新建了一个分区文件,然后再将数据直接put到这个文件夹下
hadoop fs -put order.txt /user/hive/warehouse/order/order_month=2018-02
然后查看order是否有这些数据
我们发现,在表order中,并不能看到新的分区的数据。这是怎么回事呢?我们来看一下表order的分区信息
show partitions order;
这里只有2018-01的分区信息,而没有2018-02的分区信息。原来虽然数据进入了分区目录下,但是元数据并没有2018-02的分区信息。那么此时我们需要执行如下命令来修复分区元数据
msck repair table order;
我们来看下order的partition的信息,以及是否能查询到该分区的数据
我们看到,在表order的分区信息中已经能够看到2018-02的数据,而且该分区的数据也能够在表中查询到。
注意:msck repair table tablename 是刷新表的所有分区信息,如果遇到一张非常大的表,该表有很多的分区,使用这个命令会花费特别多的时间。所以,生产环境并不推荐这种方法。而推荐下面的方法
alter table order add partition(order_month='2018-02');
我们先删除这个分区再添加
alter table order drop if exists partition (order_month='2018-02');
我们看到,在元数据中已经看不到分区2018-02的信息,然后我们再添加分区
注意:执行drop分区的时候,会把HDFS上的分区数据也一并删除掉,所以我们这里再创建一个分区文件夹,把数据put上去
然后,我们再查看该表的数据
我们可以看到新分区的数据了。
4、单级分区/多级分区
如上面的分区表order,只有一个分区,那么就叫做单级分区。两个或者两个以上的分区叫做多级分区。
我们在order的基础上再添加一个分区,表名为order2
create table order2(
order_num string,
order_time string
) partitioned by(order_month string,location string)
row format delimited fields terminated by '\t';
然后再往里面添加数据
load data local inpath '/home/hadoop/data/order.txt' into table order2 PARTITION (order_month='2018-01',location='chengdu');
注意:在查询分区表数据的时候,需要添加分区信息,不然就是查询全表数据。
我们来看一下表order2在HDFS上的存储方式
我们可以看到,order2的分区在HDFS上是有层级关系的,这样的分区就叫做多级分区。
5、静态分区和动态分区
静态分区就是我们在往分区表中导入数据时,每次都需要指定分区的信息。如我们从emp表中查出数据,插入到我们的分区表emp_partition
我们先建分区表emp_partition
CREATE TABLE emp_partition(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double)
partitioned by(deptno int)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
注意,动态分区的分区字段是来自表的列,且该列不能存在于表中。如emp_partition,deptno原属于emp,但是要作为动态分区的值,所以不能存在于emp_partition中。
我们往emp_partiton中插入数据
insert into table emp_partition partition(deptno=10)
select empno,ename,job,mgr,hiredate,sal,comm from emp where deptno=10;
我们可以在表中看见数据。但是如果deptno有很多不同的值,这种做法就很机械,而且会很费时。这种就是静态分区的缺点。我们可以用另动态分区来导入数据
insert overwrite table emp_partition partition(deptno)
select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp;
在指定分区的时候,不指定具体的分区值,而且在查询原表的时候我要把分区字段放入select语句中
这样我们就把所有的数据导入emp_partition了,而且分区也维护好了。