hive的分區表


hive的分區表
分區表使用背景:
如果一個表中數據很多,我們查詢時就很慢,耗費大量時間,如果要查詢其中部分數據該怎么辦呢,
這時我們引入分區的概念

可以根據PARTITIONED BY創建分區表,
1.一個表可以擁有一個或者多個分區,每個分區以文件夾的形式單獨存在表文件夾的目錄下;


2.分區是以偽字段(偽列)的形式在表結構中存在,通過describe tablename(或者desc [formatted ]tablename)命令可以查看到字段存在,
但是該字段不存放實際的數據內容,僅僅是分區的表示。


3.分區建表分為2種,一種是單分區,也就是說在表文件夾目錄下只有一級文件夾目錄。
另外一種是多分區,表文件夾下出現多文件夾嵌套模式。

 

CREATE TABLE `emp_1`(
`empno` int,
`ename` string,
`job` string,
`mgr` int,
`hiredate` string,
`sal` double,
`comm` double,
`deptno` int)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LOCATION
'hdfs://hadoop001:9000/user/hive/warehouse/default.db/emp'

CREATE TABLE `order_partition`(
`order_no` string,
`event_time` string)
PARTITIONED BY (
`event_month` string)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LOCATION
'hdfs://hadoop001:9000/user/hive/warehouse/d6_hive.db/order_partition'(默認)

 

單分區:

hive> CREATE TABLE order_partition (

> order_number string,

> event_time string

> )

> PARTITIONED BY (event_month string);

OK

將order.txt 文件中的數據加載到order_partition表中(加載數據的用法可參照該地址)

hive> load data local inpath '/home/hadoop/order.txt' overwrite
into table order_partition partition (event_month='2014-05');

 


hive> select * from order_partition;

 

10703007267488 2014-05-01 06:01:12.334+01 2014-05

10101043505096 2014-05-01 07:28:12.342+01 2014-05

10103043509747 2014-05-01 07:50:12.33+01 2014-05

10103043501575 2014-05-01 09:27:12.33+01 2014-05

10104043514061 2014-05-01 09:03:12.324+01 2014-05


我們在hive每創建一個分區,mysql元數據里就會有相應的元數據建立,一般會在patition這張表里有顯示。
當我們在hive里load數據進入hive以后,HDFS上相應的也會有數據,HDFS的存儲目錄可以通過在hive上執行
desc formatted tableanme 來查看 location

/user/hive/warehouse/d6_hive.db/order_partition
/user/hive/warehouse/庫名.db/表名

如果在建表時不特別指定location 那么以上的目錄就是默認目錄。

此時查看HDFS上的/user/hive/warehouse/d6_hive.db/order_partition這個目錄就能看到2014-05這個分區。
而在這個分區之下就是我們的彈性體數據文件,也就是我們load的文件。


那根據以上的操作我們是不是可以直接在HDFS的/user/hive/warehouse/d6_hive.db/order_partition目錄下
直接建分區,然后把要load的文件用put命令上傳到在HDFS上新建的分區。根據以往的建表經驗,只要把數據放到
HDFS的相應目錄上,在hive表中就能查到數據。但是在分區表中這樣是行不通的。
解釋如下:
創建分區,也就是說在HDFS文件夾目錄下會有一個分區目錄,
那么我們是不是直接可以在HDFS上創建一個目錄,再把數據加載進去呢?


[hadoop@zydatahadoop001 ~]$ hadoop fs -mkdir -p /user/hive/warehouse/order_partition/event_month=2014-06

[hadoop@zydatahadoop001 ~]$ hadoop fs -put /home/hadoop/order.txt /user/hive/warehouse/order_partition/event_month=2014-06


上傳完成后查看表order_partition
hive
> select * from order_partition

OK

10703007267488 2014-05-01 06:01:12.334+01 2014-05

10101043505096 2014-05-01 07:28:12.342+01 2014-05

10103043509747 2014-05-01 07:50:12.33+01 2014-05

10103043501575 2014-05-01 09:27:12.33+01 2014-05

10104043514061 2014-05-01 09:03:12.324+01 2014-05

Time taken: 2.034 seconds, Fetched: 5 row(s)


可以看到並沒有看到我們剛剛通過hdfs上傳后的數據,
原因是我們將文件上傳到了hdfs,hdfs是有了數據,
但hive中的元數據中還沒有,在hive中執行如下命令更新

hive>msck repair table order_partition;
還有一種方法就是在元數據MySQL中新增分區
MYSQL>ALTER TABLE order_partition ADD IF NOT EXISTS PARTITION (event_month='2014-06') ;

hive>ALTER TABLE order_partition ADD IF NOT EXISTS PARTITION (event_month='2014-06') ;(hive里執行也可以)


再次查看數據

hive> select * from order_partition;

OK

10703007267488 2014-05-01 06:01:12.334+01 2014-05

10101043505096 2014-05-01 07:28:12.342+01 2014-05

10103043509747 2014-05-01 07:50:12.33+01 2014-05

10103043501575 2014-05-01 09:27:12.33+01 2014-05

10104043514061 2014-05-01 09:03:12.324+01 2014-05

10703007267488 2014-05-01 06:01:12.334+01 2014-06

10101043505096 2014-05-01 07:28:12.342+01 2014-06

10103043509747 2014-05-01 07:50:12.33+01 2014-06

10103043501575 2014-05-01 09:27:12.33+01 2014-06

10104043514061 2014-05-01 09:03:12.324+01 2014-06


此時可以看到,在刷新以后,06分區的數據就出來了。

 

以上講的是單分區還有多分區,在hive表中體現的是又多了分區字段,在HDFS上則體現在目錄上,
多級分區和單分區在建表的時候主要就是在patition by后加分區的字段的個數。單分區只加一個,
多分區加要求的分區字段大於1個。在HDFS上每個分區都是一級目錄,目錄級別根據分區先后確定。
在加載數據的時候,在無論是多級分區還是單分區都需要在load語句最后加上patition (分區字段1=‘value’,分區字段2=‘value’)

例子展示

多分區:
hive> CREATE TABLE order_partition2 (

> order_number string,

> event_time string

> )

> PARTITIONED BY (event_month string, step string);

OK


加載數據:

hive> load data local inpath '/home/hadoop/order.txt' overwrite into table order_multi_partition partition (event_month='2014-05',step=1);


查詢:
hive> select * from order_multi_partition;

OK

110703007267488 2014-05-01 06:01:12.334+01 2014-05 1
1
10101043505096 2014-05-01 07:28:12.342+01 2014-05 1
1
10103043509747 2014-05-01 07:50:12.33+01 2014-05 1
1
10103043501575 2014-05-01 09:27:12.33+01 2014-05 1
1
10104043514061 2014-05-01 09:03:12.324+01 2014-05 1
Time taken: 0.228 seconds, Fetched: 5 row(s)
在HDFS上查詢文件結構:


[hadoop@zydatahadoop001 ~]$ hdfs dfs -ls /user/hive/warehouse/order_multi_partition/event_month=2014-05

18/01/09

Found 1 items

drwxr-xr-x - hadoop supergroup 0 2018-01-09 22:52 /user/hive/warehouse/order_multi_partition/event_month=2014-05/step=1

單級分區在HDFS上文件目錄為單級;多分區在HDFS上文件目錄為多級

 

 


(2)動態分區

 

查看官方地址

先解釋什么是動態分區:

Static Partition (SP) columns:靜態分區;

Dynamic Partition (DP) columns 動態分區。

DP columns are specified the same way as it is for SP columns – in the partition clause.
The only difference is that DP columns do not have values, while SP columns do.
In the partition clause, we need to specify all partitioning columns,
even if all of them are DP columns.

In INSERT ... SELECT ... queries, the dynamic partition columns must be specified last
among the columns in the SELECT statement and in the same order in which they appear in
the PARTITION() clause.


以上這段話就是官方對靜態動態分區的解釋
以下為總結內容


1.DP列的指定方式與SP列相同 - 在分區子句中( Partition關鍵字后面),
唯一的區別是,DP列沒有值,而SP列有值( Partition關鍵字后面只有key沒有value);

2.在INSERT … SELECT …查詢中,必須在SELECT語句中的列中最后指定動態分區列,
並按PARTITION()子句中出現的順序進行排列;

3.所有DP列 - 只允許在非嚴格模式下使用。
在嚴格模式下,我們應該拋出一個錯誤。

4.如果動態分區和靜態分區一起使用,必須是動態分區的字段在前,
靜態分區的字段在后。

 

 

**演示前先進行設置:**hive 中默認是靜態分區,想要使用動態分區,需要設置如下參數,
可以使用臨時設置,你也可以寫在配置文件(hive-site.xml)里,永久生效。
臨時配置如下
開啟動態分區(默認為false,不開啟)

set hive.exec.dynamic.partition=true;
(開啟動態分區)
set hive.exec.dynamic.partition.mode=nonstrict;

(指定動態分區模式,默認為strict,即必須指定至少一個分區為靜態分區,
nonstrict模式表示允許所有的分區字段都可以使用動態分區。)

1
2
3
創建員工的動態分區表,分區字段為deptno;

CREATE TABLE emp_dynamic_partition
(
empno int,
ename string,
job string,
mgr int,
hiredate string,
salary double,
comm double
)

PARTITIONED BY (deptno int)

ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t";

1
2
3
4
5
6
7
8
9
10
11

如果使用靜態分區,根據deptno要寫多條語句如下:

CREATE TABLE emp_partition (
empno int,
ename string,
job string,
mgr int,
hiredate string,
salary double,
comm double
)

PARTITIONED BY (deptno int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t";

 

insert into table emp_partition partition(deptno=10)
select empno,ename ,job ,mgr ,hiredate ,salary ,comm
from emp where deptno=10;


insert into table emp_partition partition(deptno=20)
select empno,ename ,job ,mgr ,hiredate ,salary ,comm from emp where deptno=20;


insert into table emp_partition partition(deptno=30)
select empno,ename ,job ,mgr ,hiredate ,salary ,comm from emp where deptno=30;


查詢結果:

hive> select * from emp_partition;

OK

7782 CLARK MANAGER 7839 1981/6/9 2450.0 NULL 10

7839 KING PRESIDENT NULL 1981/11/17 5000.0 NULL 10

7934 MILLER CLERK 7782 1982/1/23 1300.0 NULL 10

7369 SMITH CLERK 7902 1980/12/17 800.0 NULL 20

7566 JONES MANAGER 7839 1981/4/2 2975.0 NULL 20

7788 SCOTT ANALYST 7566 1987/4/19 3000.0 NULL 20

7876 ADAMS CLERK 7788 1987/5/23 1100.0 NULL 20

7902 FORD ANALYST 7566 1981/12/3 3000.0 NULL 20

7499 ALLEN SALESMAN 7698 1981/2/20 1600.0 300.0 30

7521 WARD SALESMAN 7698 1981/2/22 1250.0 500.0 30

7654 MARTIN SALESMAN 7698 1981/9/28 1250.0 1400.0 30

7698 BLAKE MANAGER 7839 1981/5/1 2850.0 NULL 30

7844 TURNER SALESMAN 7698 1981/9/8 1500.0 0.0 30

7900 JAMES CLERK 7698 1981/12/3 950.0 NULL 30


我們再來看看使用動態分區的效果並注意他的基本語法與靜態分區的區別:

insert into table emp_dynamic_partition partition(deptno)
select empno,ename ,job ,mgr ,hiredate ,salary ,comm, deptno from emp;

一條語句完成

hive> select * from emp_dynamic_partition;

OK

7782 CLARK MANAGER 7839 1981/6/9 2450.0 NULL 10

7839 KING PRESIDENT NULL 1981/11/17 5000.0 NULL 10

7934 MILLER CLERK 7782 1982/1/23 1300.0 NULL 10

7369 SMITH CLERK 7902 1980/12/17 800.0 NULL 20

7566 JONES MANAGER 7839 1981/4/2 2975.0 NULL 20

7788 SCOTT ANALYST 7566 1987/4/19 3000.0 NULL 20

7876 ADAMS CLERK 7788 1987/5/23 1100.0 NULL 20

7902 FORD ANALYST 7566 1981/12/3 3000.0 NULL 20

7499 ALLEN SALESMAN 7698 1981/2/20 1600.0 300.0 30

7521 WARD SALESMAN 7698 1981/2/22 1250.0 500.0 30

7654 MARTIN SALESMAN 7698 1981/9/28 1250.0 1400.0 30

7698 BLAKE MANAGER 7839 1981/5/1 2850.0 NULL 30

7844 TURNER SALESMAN 7698 1981/9/8 1500.0 0.0 30

7900 JAMES CLERK 7698 1981/12/3 950.0 NULL 30

 

查看HDFS上文件目錄結構
[hadoop@zydatahadoop001 ~]$ hdfs dfs -ls /user/hive/warehouse
Found 5 items

drwxr-xr-x - hadoop supergroup 0 2018-01-09 20:30 /user/hive/warehouse/emp

drwxr-xr-x - hadoop supergroup 0 2018-01-10 00:38 /user/hive/warehouse/emp_dynamic_partition

drwxr-xr-x - hadoop supergroup 0 2018-01-10 00:34 /user/hive/warehouse/emp_partition

drwxr-xr-x - hadoop supergroup 0 2018-01-09 22:52 /user/hive/warehouse/order_multi_partition

drwxr-xr-x - hadoop supergroup 0 2018-01-09 22:42 /user/hive/warehouse/order_partition

 

 

 

動態分區時,第一次執行會碰到這個錯誤動態分區是嚴格模式,需要設置成非嚴格模式執行set hive.exec.dynamic.partition.mode=nonstrict

hive (d6_hive)> insert into emp_dynamic_partition1 partition(deptno) select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp;
FAILED: SemanticException [Error 10096]: Dynamic partition strict mode requires at least one static partition column. To turn this off set hive.exec.dynamic.partition.mode=nonstrict


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM