Hive基础之分区表

我们在做数据挖掘和分析的时候有时候只是针对某一段时间或者某一个月的数据,而我们在创建表的时候是将所有时间的数据都放在一起,这样就会导致我们在进行分析的时候会分析所有的数据,如果数据量很大的时候效率就会很慢,这时候Hive就提供一种特性叫分区表,可以针对一个月的数据进行查询和分析。原来可能要分析100G的数据文件,经过分区后可能只需要分析10G的文件,这样可以大大提升数据分析的效率。下面我们就来详细看一下hive的分区表。

1.分区表定义

分区表实际上就是对应一个HDFS文件系统上的独立的文件夹,该文件夹下是该分区的所有的数据文件。Hive中的分区就是分目录,把一个大的数据集根据业务需要分割成更小的数据集。这个在企业中会特别有用,尤其是分区表和外部表相结合,应用特别广泛。
在hive中查询时通过WHERE子句中的表达式来选择查询所需要的指定的分区,这样的查询效率会提高很多。
还是以emp表为例,分区表的创建脚本如下:

create EXTERNAL table IF NOT EXISTS default.emp_part(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int
)
partitioned by (month string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' ;
hive (default)> create EXTERNAL table IF NOT EXISTS default.emp_part(
              > empno int,
              > ename string,
              > job string,
              > mgr int,
              > hiredate string,
              > sal double,
              > comm double,
              > deptno int
              > )
              > partitioned by (month string)
              > ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' ;
OK
Time taken: 0.996 seconds
hive (default)> show tables;
OK
tab_name
dept
dept_cats
emp
emp_ext
emp_ext2
emp_part
Time taken: 0.171 seconds, Fetched: 6 row(s)

查看分区表的信息:

hive (default)> desc formatted emp_part;
OK
col_name        data_type       comment
# col_name              data_type               comment             
                 
empno                   int                                         
ename                   string                                      
job                     string                                      
mgr                     int                                         
hiredate                string                                      
sal                     double                                      
comm                    double                                      
deptno                  int                                         
                 
# Partition Information          
# col_name              data_type               comment             
                 
month                   string                                      
                 
# Detailed Table Information             
Database:               default                  
Owner:                  hive                     
CreateTime:             Thu Feb 14 21:37:29 CST 2019     
LastAccessTime:         UNKNOWN                  
Protect Mode:           None                     
Retention:              0                        
Location:               hdfs://node1:8020/user/hive/warehouse/emp_part   
Table Type:             EXTERNAL_TABLE           
Table Parameters:                
        EXTERNAL                TRUE                
        numPartitions           0                   
        transient_lastDdlTime   1550151449          
                 
# Storage Information            
SerDe Library:          org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe      
InputFormat:            org.apache.hadoop.mapred.TextInputFormat         
OutputFormat:           org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat       
Compressed:             No                       
Num Buckets:            -1                       
Bucket Columns:         []                       
Sort Columns:           []                       
Storage Desc Params:             
        field.delim             \t                  
        serialization.format    \t                  
Time taken: 0.563 seconds, Fetched: 41 row(s)

可以看到其中的分区信息如下:

# Partition Information          
# col_name              data_type               comment             
                 
month                   string         

其中分区的字段是month,分区的数据类型是string类型。

2.加载数据到分区表

要加载数据到分区表,只需在原来的加载数据的语句上增加partition关键字,同时指定分区的字段值即可。

hive (default)> load data local inpath '/opt/datas/emp.txt' into table default.emp_part partition (month='201902') ;
Loading data to table default.emp_part partition (month=201902)
Partition default.emp_part{month=201902} stats: [numFiles=1, numRows=0, totalSize=659, rawDataSize=0]
OK
Time taken: 5.955 seconds

查看hdfs上的文件目录:

hive (default)> dfs -ls /user/hive/warehouse/emp_part;
Found 1 items
drwxrwxrwt   - hive hive          0 2019-02-14 21:45 /user/hive/warehouse/emp_part/month=201902
hive (default)> dfs -ls /user/hive/warehouse/emp_part/month=201902;
Found 1 items
-rwxrwxrwt   3 hive hive        659 2019-02-14 21:45 /user/hive/warehouse/emp_part/month=201902/emp.txt

可以看到在/user/hive/warehouse/emp_part目录下会多一个month=201902的子目录,而数据文件就存放在该目录下。

3.查询分区数据

直接使用分区字段就可以查询分区中的数据:

hive (default)> select * from emp_part where month = '201902' ;
OK
empno   ename   job     mgr     hiredate        sal     comm    deptno  month
7369    SMITH   CLERK   7902    1980-12-17      800.0   NULL    20      201902
7499    ALLEN   SALESMAN        7698    1981-2-20       1600.0  300.0   30     201902
7521    WARD    SALESMAN        7698    1981-2-22       1250.0  500.0   30     201902
7566    JONES   MANAGER 7839    1981-4-2        2975.0  NULL    20      201902
7654    MARTIN  SALESMAN        7698    1981-9-28       1250.0  1400.0  30     201902
7698    BLAKE   MANAGER 7839    1981-5-1        2850.0  NULL    30      201902
7782    CLARK   MANAGER 7839    1981-6-9        2450.0  NULL    10      201902
7788    SCOTT   ANALYST 7566    1987-4-19       3000.0  NULL    20      201902
7839    KING    PRESIDENT       NULL    1981-11-17      5000.0  NULL    10     201902
7844    TURNER  SALESMAN        7698    1981-9-8        1500.0  0.0     30     201902
7876    ADAMS   CLERK   7788    1987-5-23       1100.0  NULL    20      201902
7900    JAMES   CLERK   7698    1981-12-3       950.0   NULL    30      201902
7902    FORD    ANALYST 7566    1981-12-3       3000.0  NULL    20      201902
7934    MILLER  CLERK   7782    1982-1-23       1300.0  NULL    10      201902
Time taken: 5.537 seconds, Fetched: 14 row(s)

这样我们就可以实现按月或者按日来进行查询数据,在互联网中对网站日志进行分析的时候经常会遇到按日或者按月统计PV值,这个时候使用分区表就会大幅的提高统计效率。

如果要统计一个季度的数据,这可以将三个月的查询结果union在一起,然后得出一个最终结果。

select count(distinct ip) from emp_part where month = '201901'
union
select count(distinct ip) from emp_part where month = '201902'
union
select count(distinct ip) from emp_part where month = '201903';

使用上面的查询语句就可以得出一个季度的统计结果,在企业的应用中,这个是比较常见的。

4.二级分区

前面介绍了只有一个字段的分区,hive还支持二级分区,可以在之前的分区的基础上再增加一个字段。二级分区表的使用脚本如下:

create EXTERNAL table IF NOT EXISTS default.emp_part(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int
)
partitioned by (month string,day string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' ;

load data local inpath '/opt/datas/emp.txt' into table default.emp_part partition (month='201902',day='14') ;

select * from emp_part where month = '201902' and day='14' ;

5.注意事项

在没有加分区字段的表,我们只要将数据文件上传到hdfs上对应的文件夹下就可以查询到数据,但是分区表不行。我们重新建一张分区表并实验一下。

hive (default)> create table IF NOT EXISTS default.dept_part(
              > deptno int,
              > dname string,
              > loc string
              > )
              > partitioned by (day string)
              > ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
OK
Time taken: 0.313 seconds
hive (default)> show tables;
OK
tab_name
dept
dept_cats
dept_part
emp
emp_ext
emp_ext2
emp_part
Time taken: 0.088 seconds, Fetched: 7 row(s)
hive (default)> dfs -mkdir -p /user/hive/warehouse/dept_part/day=20190214 ;
hive (default)> dfs -put /opt/datas/dept.txt /user/hive/warehouse/dept_part/day=20190214 ;
hive (default)> dfs -ls /user/hive/warehouse/dept_part/day=20190214;
Found 1 items
-rw-r--r--   3 hive hive         82 2019-02-14 22:16 /user/hive/warehouse/dept_part/day=20190214/dept.txt
hive (default)> select * from dept_part;
OK
deptno  dname   loc     day
Time taken: 0.214 seconds

可以看到,虽然我们把数据文件放到了对应的分区目录下,但是我们在hive中还是查不到数据。原来分区表相关的元数据是保持在数据库中的,我们直接上传文件到hdfs中,但是分区表的元数据没有创建,所以我们查询不到数据。我们登录到mysql数据库中查看一下元数据的信息:

[mysql@node1 ~]$ mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 459
Server version: 5.6.42-log MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use hive;
Database changed
mysql> select * from PARTITIONS;
+---------+-------------+------------------+--------------+-------+--------+----------------+
| PART_ID | CREATE_TIME | LAST_ACCESS_TIME | PART_NAME    | SD_ID | TBL_ID | LINK_TARGET_ID |
+---------+-------------+------------------+--------------+-------+--------+----------------+
|      79 |  1550151929 |                0 | month=201902 |   129 |     48 |           NULL |
+---------+-------------+------------------+--------------+-------+--------+----------------+
1 row in set (0.00 sec)

可以看到分区表PARTITIONS中并没有我们后来新增的那个分区信息。如果要在hive中能够正常查询分区表信息就需要在这张表中插入相应的数据。解决这个问题有两种方式:

第一种:使用msck命令

hive (default)> msck repair table dept_part ;
OK
Partitions not in metastore:    dept_part:day=20190214
Repair: Added partition to metastore dept_part:day=20190214
Time taken: 0.396 seconds, Fetched: 2 row(s)
hive (default)> select * from dept_part;
OK
deptno  dname   loc     day
10      ACCOUNTING      NEW YORK        20190214
20      RESEARCH        DALLAS  20190214
30      SALES   CHICAGO 20190214
40      OPERATIONS      BOSTON  20190214
Time taken: 0.188 seconds, Fetched: 4 row(s)

可以看到现在能够查询出来相应的数据了。再重新查询一下mysql中的数据:

mysql> select * from PARTITIONS;
+---------+-------------+------------------+--------------+-------+--------+----------------+
| PART_ID | CREATE_TIME | LAST_ACCESS_TIME | PART_NAME    | SD_ID | TBL_ID | LINK_TARGET_ID |
+---------+-------------+------------------+--------------+-------+--------+----------------+
|      79 |  1550151929 |                0 | month=201902 |   129 |     48 |           NULL |
|      98 |  1550154626 |                0 | day=20190214 |   158 |     57 |           NULL |
+---------+-------------+------------------+--------------+-------+--------+----------------+
2 rows in set (0.00 sec)

可以看到分区表中多了一条数据。

第二种:使用alter命令

我们再新建一个分区,在这个分区下导入同样的数据。

hive (default)> dfs -mkdir -p /user/hive/warehouse/dept_part/day=20190215 ;
hive (default)> dfs -put /opt/datas/dept.txt /user/hive/warehouse/dept_part/day=20190215 ;
hive (default)> alter table dept_part add partition(day='20190215');
OK
Time taken: 0.23 seconds
hive (default)> select * from dept_part;
OK
deptno  dname   loc     day
10      ACCOUNTING      NEW YORK        20190214
20      RESEARCH        DALLAS  20190214
30      SALES   CHICAGO 20190214
40      OPERATIONS      BOSTON  20190214
10      ACCOUNTING      NEW YORK        20190215
20      RESEARCH        DALLAS  20190215
30      SALES   CHICAGO 20190215
40      OPERATIONS      BOSTON  20190215
Time taken: 0.204 seconds, Fetched: 8 row(s)

可以看出,在修复分区信息后能过查询出来8条记录,说明我们新建的分区已经生效。在看一下分区表中的数据:

mysql> select * from PARTITIONS;
+---------+-------------+------------------+--------------+-------+--------+----------------+
| PART_ID | CREATE_TIME | LAST_ACCESS_TIME | PART_NAME    | SD_ID | TBL_ID | LINK_TARGET_ID |
+---------+-------------+------------------+--------------+-------+--------+----------------+
|      79 |  1550151929 |                0 | month=201902 |   129 |     48 |           NULL |
|      98 |  1550154626 |                0 | day=20190214 |   158 |     57 |           NULL |
|     101 |  1550155039 |                0 | day=20190215 |   162 |     57 |           NULL |
+---------+-------------+------------------+--------------+-------+--------+----------------+
3 rows in set (0.00 sec)

可以看出分区表中的元数据又多了一条,且其对应的分区名称为day=20190215。

6.查看表的分区信息

使用show partitions命令可以查看分区表中有多少个分区。

hive (default)> show partitions dept_part ;
OK
partition
day=20190214
day=20190215
Time taken: 0.199 seconds, Fetched: 2 row(s)

更多有关大数据的内容请关注微信公众号:大数据与人工智能初学者
扫描下面的二维码即可关注:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值