Hive中靜態分割槽表 & 動態分割槽表
概念的引入
在Web系的統日誌表中,當我們的操作很多時,通常所會採取的辦法是:每一次操作都要記錄一條日誌,而這些日誌很多都是按日/月進行分割槽的;如果不這樣做,到時候查起表來回非常非常大。
假設有以下分割槽:
CLICK_LOG_20180801
CLICK_LOG_20180802
CLICK_LOG_20180803
當我們進行這樣進行分割槽之後,對比原來只有一張表CLICK_LOG,會有以下優點:可以提高我們的查詢效率
通過列印的日誌觀察不使用分割槽表所帶來的問題:
hive>select deptno, count(1) from emp group by deptno;
列印的資訊中有:
HDFS Read: 8012,表示讀取資料量大小為8012(讀取方式為全表讀取)
我們假設:emp表中有10億條資料
那麼在我們進行全表讀取的時候,效率就會很低
但是當我們使用分割槽表之後,HDFS上資料儲存的目錄就會成為:
/user/hive/warehouse/emp/day=20180808/
/user/hive/warehouse/emp/day=20180809/
而我們去Hive表中查詢資料時,可以這樣寫:
hive>select ... from xxx where day=20180808
從而丟擲Hive中要使用分割槽表的原因:
這樣的操作,可以減少資料的讀取量,進而提升效率
報錯解決方案
在建立Hive表之後,匯入資料的時候,可能會出現報錯:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Specified key was too long; max key length is 767 bytes
報錯解決方案/亂碼解決辦法:
注意:改變mysql設定,不能改變已經存在的表。我們需要轉換表的編碼。
mysql>alter database 資料庫名稱 character set latin1;
mysql>use 資料庫名稱;
mysql>alter table PARTITIONS convert to character set latin1;
mysql>alter table PARTITION_KEYS convert to character set latin1;
靜態單級分割槽表的使用
從本地匯入資料 & Hive表資料與HDFS資料的區別 & Hive表結構的變化
建立一張表
create table order_partition(
order_number string,
event_time string
)
PARTITIONED BY(event_month string)
row format delimited fields terminated by '\t';
載入資料:
hive>load data local inpath '/opt/data/order_created.txt' overwrite
into table order_partition PARTITION(event_month='201405');
資料匯入成功,對比hive中查表得到的資料與hdfs中儲存的資料:
hive>select * from order_partition;
$>hadoop fs -text /user/hive/warehouse/order_partition/event_month=201405/order_created.txt
發現
在Hive表中,能查到分割槽列的資料,但是在HDFS的資料表中查不到分割槽列的資料
因為:分割槽列不是表中的一個實際的列,其實質是一個偽列,而HDFS中儲存的是真正的資料,因此肯定看不到該列
查看錶結構:
hive>desc formatted order_partition;
多了Partition Information的資訊:
從HDFS匯入資料 & 兩種方式修改表的分割槽資訊 & 表的分割槽資訊的查詢
在HDFS上建立相應的目錄,並上傳資料:
$>hadoop fs -mkdir /user/hive/warehouse/order_partition/event_month=201406
$>hadoop fs -put /opt/data/order_created.txt /user/hive/warehouse/order_partition/event_month=201406
HDFS中event_month=201406目錄下,已經傳入資料:
但是,出現了一個問題:
雖然,我們在HDFS上添加了event_month=201406的分割槽資料,但是Hive表中的資料卻仍然沒有改變
我們通過查詢Hive表上的資料,驗證發現數據確實沒有新增進來,資料仍然是5條
hive>select * from order_partition;
開始查詢原因:
首先,我們對mysql裡的元資料資訊進行查詢:
mysql>use zhaotao_hive;
mysql>select * from PARTITIONS;
mysql>select * from PARTITION_KEYS;
發現mysql中,分割槽資訊並沒有發生改變
語法:
ALTER TABLE table_name ADD [IF NOT EXISTS] PARTITION partition_spec [LOCATION 'location'][, PARTITION partition_spec [LOCATION 'location'], ...];
partition_spec:
: (partition_column = partition_col_value, partition_column = partition_col_value, ...)
修改分割槽資訊:
hive>ALTER TABLE order_partition ADD IF NOT EXISTS PARTITION(event_month='201406');
成功解決,再度查詢資料
hive>select * from order_partition;
mysql>select * from PARTITIONS;
mysql>select * from PARTITION_KEYS;
Hive表中的資料:
MySQL中的元資料資訊:
通過上圖,我們發現數據都進來了,從HDFS中匯入分割槽資料成功
語法:
MSCK REPAIR TABLE table_name;
$>hadoop fs -mkdir /user/hive/warehouse/order_partition/event_month=201407
$>hadoop fs -put /opt/data/order_created.txt /user/hive/warehouse/order_partition/event_month=201407
hive>MSCK REPAIR TABLE order_partition;
執行完這句話之後,Hive表中的資料直接進來了,mysql的元資料資訊也增加了
不建議這樣使用,太暴力了
舉個例子:
metastore存了一年了,5分鐘1個分割槽,1天就是288個分割槽
假設有100條業務線
一旦這樣一執行,可能會造成的情況,就是整個資料庫出現風險
因此,生產上建議使用alter
查詢分割槽資訊
hive>show partitions order_partition;
(可以通過查閱原始碼,去驗證show partitions從mysql的哪張表裡來讀取分割槽資料資訊 )
【注意】
如果沒有mysql上的元資料資訊,HDFS上的資料是和hive中執行的sql無法關聯起來的
因此,每次執行一個SQL語句,都必須要知曉底層的metastore到底幹了些什麼事情,這對學習Hive會有很大的幫助
靜態多級分割槽表的使用
建立表
create table order_mulit_partition(
order_number string,
event_time string
)
PARTITIONED BY(event_month string, step string)
row format delimited fields terminated by '\t';
從本地向靜態多級分割槽表匯入資料
hive>load data local inpath '/opt/data/order_created.txt' overwrite
into table order_mulit_partition PARTITION(event_month='201405', step='1');
注意:在多分割槽使用的時候注意: 每個分割槽欄位要寫明,包括順序等等
動態分割槽表的使用
在Hive中,使用動態分割槽表,這種方式在工作中常用
需求
按照不同部門作為分割槽導資料到目標表
使用靜態分割槽表來完成
建立靜態分割槽表:
create table emp_static_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';
插入資料:
hive>insert into table emp_static_partition partition(deptno=10)
select empno , ename , job , mgr , hiredate , sal , comm from emp where deptno=10;
查詢資料:
hive>select * from emp_static_partition;
使用動態分割槽表來完成
建立動態分割槽表:
create table emp_dynamic_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';
【注意】動態分割槽表與靜態分割槽表的建立,在語法上是沒有任何區別的
插入資料:
hive>insert into table emp_dynamic_partition partition(deptno)
select empno , ename , job , mgr , hiredate , sal , comm, deptno from emp;
【注意】分割槽的欄位名稱,寫在最後,有幾個就寫幾個 與靜態分割槽相比,不需要where了
需要設定屬性的值:
hive>set hive.exec.dynamic.partition.mode=nonstrict;
【注意】不設定,會報錯
查詢資料:
hive>select * from emp_dynamic_partition;
分割槽列為deptno,實現了動態分割槽
動態分割槽表的總結
動態分割槽無需手工指定資料匯入的具體分割槽
而是由select的欄位(欄位寫在最後,有幾個寫幾個)自行決定匯出到哪一個分割槽中
並自動建立相應的分割槽,使用上更加方便快捷
工作中用的非常多