1. 程式人生 > >hive 分割槽表簡單梳理

hive 分割槽表簡單梳理

環境相關:
OS:CentOS release 6.9
IP:192.168.77.10
hadoop-2.6.0-cdh5.7.1
hive-1.1.0-cdh5.7.1
mysql5.1

1. 相關說明

  • 分割槽表的一個分割槽對應hdfs上的一個目錄
  • 分割槽表包括靜態分割槽表和動態分割槽表,根據分割槽會不會自動建立來區分
  • 多級分割槽表,即建立的時候指定 PARTITIONED BY (event_month string,loc string),根據順序,級聯建立 event_month=XXX/loc=XXX目錄,其他和一級的分割槽表是一樣的

準備測試用的資料:

for i in $(seq 20)
do 
  echo -e  "$(date -d "$RANDOM minute ago"  +%F' '%T'.'%N)"
done|sort -nk1|awk '{print NR"\t"$0}'>/tmp/order_created.txt
cat /tmp/order_created.txt

2. 靜態分割槽表

建立靜態分割槽表,載入資料:

use test1;
drop table test1.order_created_partition purge;
CREATE TABLE order_created_partition (
order_number string,
event_time string
)
PARTITIONED BY
(event_month string) ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t";
-- 建表語句,指定分割槽欄位為event_month,這個欄位是偽列 -- 會在資料load到表的這個分割槽時,在hdfs上建立名為event_month=2017-12的子目錄 LOAD DATA LOCAL INPATH "/tmp/order_created.txt" OVERWRITE INTO TABLE order_created_partition PARTITION (event_month='2017-12'); -- 使用 hdfs dfs -cat .../order_created_partition/event_month=2017-12/order_created.txt
-- 檢視資料檔案中並沒有event_month這一列 select * from test1.order_created_partition; -- 分割槽表全表掃描,不推薦 select * from test1.order_created_partition where event_month='2017-12'; -- 使用where子句,過濾分割槽欄位,遍歷某個分割槽 -- 以上兩個SQL可以查到列event_month資訊 -- 而使用hdfs dfs -cat看不到該列,說明分割槽表的分割槽列是偽列 -- 實際上是hdfs中的分割槽目錄的體現

新增分割槽,load資料:

alter table test1.order_created_partition
  add partition (event_month='2018-01');
LOAD DATA LOCAL INPATH "/tmp/order_created.txt" 
OVERWRITE INTO TABLE order_created_partition
PARTITION (event_month='2018-01');
-- 新增一個分割槽,將一模一樣的資料檔案載入到該分割槽
select * from test1.order_created_partition
 where event_month='2018-01';
-- 查到了該分割槽的記錄

LOAD DATA LOCAL INPATH "/tmp/order_created.txt"
INTO TABLE order_created_partition
PARTITION (event_month='2018-01');
select * from test1.order_created_partition
 where event_month='2018-01';
-- 不使用OVERWRITE引數,會追加資料到分割槽

LOAD DATA INPATH "/user/hive/warehouse/test1.db/order_created_partition/event_month=2017-12/order_created.txt"
INTO TABLE order_created_partition
PARTITION (event_month='2018-01');
-- 如果從hdfs中載入資料,則原來的路徑檔案被轉移掉
  • 可以看出,所謂的分割槽,是人為定義的,跟業務資料實際上是不是屬於該分割槽沒關係,比如將相同的資料分別插入兩個分割槽中,再比如插入的資料有2017-12月份的和2018-01月份的資料

刪除分割槽:

alter table test1.order_created_partition
  drop partition (event_month='2018-01');
-- 從hdfs中已經看不到event_month=2018-01的分割槽子目錄了

查詢裝入資料:

insert overwrite table order_created_partition 
 partition(event_month='2017-11')
select order_number,event_time
  from order_created_partition 
 where event_month='2018-02';
-- 使用查詢裝入資料到分割槽中,分割槽可以是當前不存在的
-- 因為查詢的是分割槽表,需要注意偽列和被裝入的分割槽表列的對應關係

手工建立hdfs目錄和檔案,新增分割槽的情況:
靜態分割槽表如果手工建立對應的hdfs目錄上傳檔案,而不使用分割槽建立命令和load資料到分割槽的命令,分割槽表中無法查到該分割槽資訊,需要重新整理,這種新增分割槽的途徑是不合法的:

hdfs dfs -mkdir -p /user/hive/warehouse/test1.db/order_created_partition/event_month=2018-02
hdfs dfs -put /tmp/order_created.txt  /user/hive/warehouse/test1.db/order_created_partition/event_month=2018-02
hdfs dfs -ls /user/hive/warehouse/test1.db/order_created_partition/event_month=2018-02
hive
select * from test1.order_created_partition
 where event_month='2018-02';
-- 此時是查不到該分割槽的
MSCK REPAIR TABLE order_created_partition;
-- 修復表資訊之後可以查詢
show partitions order_created_partition;
-- 檢視該表的所有分割槽

3. 動態分割槽表

use test1;
select * from emp;
-- 根據從前實驗建立的emp表
-- 將emp表的資料按照部門分組,並將資料載入到其對應的分組中去
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';
-- 根據部門編號分割槽,原表中的部門編號欄位就沒有必要建立了
-- 而是由分割槽表建立的偽列來替代
set hive.exec.dynamic.partition.mode=nonstrict;
-- 設定動態分割槽模式為非嚴格模式
insert into table emp_partition partition(deptno)
select empno,ename,job,mgr,hiredate,sal,comm ,deptno from emp;
-- 動態分割槽表的資料插入語句
-- partition(deptno) 而不是 partition(deptno=XXX)
-- select 子句從原表查出來的列數和列序要和分割槽表列數和列序保持一致
-- select 子句最後一列要為分割槽表的分割槽列
-- 不在需要where子句
-- 設定動態分割槽模式為非嚴格模式
-- set hive.exec.dynamic.partition.mode=nonstrict;

動態分割槽表就這麼簡單。

[TOC]