1. 程式人生 > >Hive基礎(3):表分類、檢視、資料載入方式、資料的匯出、本地模式

Hive基礎(3):表分類、檢視、資料載入方式、資料的匯出、本地模式

========================================================================
複習:
1、載入資料的兩種模式
讀模式
資料被載入到資料庫的時候,不對其合法性進行校驗,只在查詢等操作的時候進行校驗,特點:載入速度快,適合大資料的載入
寫模式
資料被載入到資料庫的時候,需對其合法性進行校驗,資料庫中的資料都是合法的資料,特點:載入速度慢,但是查詢速度快。
Hive採用的是讀模式,資料被載入到資料庫的時候,不對其合法性進行校驗,對於在查詢過程出現的非法資料顯示為NULL。
2、Hive表中載入資料的兩種方式
load data local inpath linux_fs_path into table tblName;
hadoop fs -put linux_path hdfs_uri;
3、Hive中複合資料型別和各種預設的分隔符:
複合資料型別:array、map、struct
array元素的引用:arrayName[index]
map元素的引用:mapName['key']
struct元素的引用:structName.item
預設分隔符:
行的預設分隔符:'\n'
列的預設分隔符:'\001' --> ctrl+v ctrl+a
集合元素的預設分隔符:'\002' --> ctrl+v ctrl+b
map k-v的預設分隔符:'\003' --> ctrl+v ctrl+c
在建立表寫分隔符的時候,是有順序要求的,如下:
create table tblName(
columns columns_type comment 'comment'
) row format delimited--->指明要使用自定義新增分隔符
fields terminated by '列分隔符'  -->讀取資料的時候是一行一行的,讀取好了一行之後,對資料解析,所以要用列分隔符拆分每一列
collection items terminated by '集合元素分割符' -->如果列是集合的話,就要跟著拆分集合元素
map keys terminated by 'map-key分割符' -->map 也是集合中的元素,碰到是map的型別了再解析map
lines terminated by '行分隔符'; -->解析完一行需要知道下一行,所以這個時候要知道行分隔符了
==========================================================================================
1、表的分類

受控表
所謂受控表,我們也經常叫內部表,和外部表對應起來,就是說表的資料的生命週期收表的控制,當表定義被刪除的時候,表中的資料隨之一併被刪除。
建立一張表,其對應在hive中就有了表記錄,在metastore表TBLS中就有表定義,當我們一旦從hive中刪除一張表的定義之後,其表中的資料也就不復存在了,
在metastore中的定義也就不存在了
外部表
和受控表相對的,怎麼相對呢,你的內部表的資料的生命週期受表定義的影響不是,外部表的不是這樣的,資料的生命週期,
或者說資料存在與否和表的定義互不約束,表中的資料呢,只是表對hdfs上相應檔案的一個引用而已,當刪除表定義的時候,表中的資料依然存在。
如何建立外部表?
create external table tblName(colName colType...);
external,是外部表呀,必須要和內部表區別一下
載入資料

alter table tblName set location 'hdfs_absolute_uri';
一個是location,不是引用hdfs的資料嗎,
當然在建立表的時候就可以告訴它引用資料的地方
create external table tblName(colName colType...) location 'hdfs_absolute_uri';
需要說明的是:在建立表的時候指定的hdfs_absolute_uri是一個目錄
注意:內部表和外部表是可以進行轉換的,只需要進行一些簡單的設定就可以了
內——>外
alter table tblName set tblproperties('EXTERNAL'='TRUE');
外——>內
alter table tblName set tblproperties('EXTERNAL'='FALSE');
分割槽表
假設伺服器叢集每天都產生一個日誌資料檔案,把資料檔案統一儲存到HDFS中。我們如果想查詢某一天的資料的話,hive執行的時候會對所有檔案都掃描一遍,
判斷是否是指定的日期。
  可以讓日期作為一個子目錄。當hive查詢的時候,根據日期去判斷子目錄。然後掃描符合條件的子目錄中的資料檔案。
如何建立一張分割槽表?
只需要在之前的建立表後面加上分割槽欄位就可以了,eg.
  create table tblName (
  id int comment 'ID',
  name string comment 'name' 
  ) partitioned by (dt date comment 'create time')
  row format delimited
  fields terminated by '\t';
如何載入資料?
load data local inpath linux_fs_path into table tblName partition(dt='2015-12-12'); 
上面的語句會在hive表tblName中自動建立一個分割槽,以dt='2015-12-12'為資料夾名稱,下面存放上傳的資料
相應的在metastore中的partitions中就有了相應的記錄。
分割槽的一些操作:

查詢分割槽中的資料:select * from tblName where dt='2015-12-13';(分割槽相當於where的一個條件)
手動建立一個分割槽:alter table tblName add partition(dt='2015-12-13');
檢視分割槽表有哪些分割槽:show partitions tblName;
刪除一個分割槽:alter table tblName drop partition(dt='2015-12-12');
多個分割槽如何建立?
和單分割槽表的建立類似:
  create table tblName (
  id int comment 'ID',
  name string comment 'name' 
  ) partitioned by (year int comment 'admission year', school string comment 'school name')
  row format delimited
  fields terminated by '\t';
同時也可以從hdfs上引用資料:
alter table tblName partition(year='2015', school='crxy') set location hdfs_uri;
注意:
必須得現有分割槽,必須要使用hdfs絕對路徑
相應的分割槽下面沒有資料對吧,你刪了分割槽也不會影響原來的資料對不對,有點動態引用的意思。
桶表
桶表是對資料進行雜湊取值,然後放到不同檔案中儲存。
  分桶是將資料及分解成更容易管理的若干部分的另一種技術。
  如果進行表連線操作,那麼就需要對兩張表的資料進行全掃描。非常耗費時間。可以針對連線欄位進行優化。
  分桶這種情況下呢,對於相似的表中的資料進行比較的話就非常的方便了,只要對比相應的桶中的資料就可了。
如何建立桶表?
create table tblName_bucket(id int) clustered by (id) into 3 buckets;
說明:
clustered by :按照什麼分桶
into x buckets:分成x個桶
如何載入資料?
不能使用load data這種方式,需要從別的表來引用
insert into table tblName_bucket select * from tbl_other;
注意:在插入資料之前需要先設定開啟桶操作,不然插入資料不會設定為桶!!!
set hive.enforce.bucketing=true;
桶表的主要作用:
資料抽樣
提高某些查詢效率
==========================================================================================
2、檢視
  Hive中,也有檢視的概念,那我們都知道檢視實際上是一張虛擬的表,是對資料的邏輯表示,只是一種顯示的方式,主要的作用呢:
  1、檢視能夠簡化使用者的操作
  2、檢視使使用者能以多鍾角度看待同一資料
3、檢視對重構資料庫提供了一定程度的邏輯獨立性
4、檢視能夠對機密資料提供安全保護
5、適當的利用檢視可以更清晰的表達查詢
  那我們在Hive中如何來建立一個檢視呢?
create view t_view as select * from otherTbl;
關於檢視的幾點說明:
1、只有檢視的定義,沒有相應的物理結構
也就是說只有在metastore中有和hdfs中的對映關係,在hdfs中沒有相應的資料夾
2、操作
可以把檢視當做表的一個衍伸,所以對hive表的各種操作,在檢視上就有。
==========================================================================================
3、總結資料載入方式
說明:[]表示可有可無,<>表示必須要有
1°、從linux fs和hdfs中載入
load data [local] inpath 'path' [overwrite] into table tblName [partition_sepc];
幾個關鍵字有無的說明:
local:
有:資料從本地path中載入,其中path可以是絕對路徑,也可以是相對路徑。
無:資料從hdfs上的相應路徑path中移動資料到表tblName下,相當於hadoop fs -mv hdfs_uri_1 hdfs_uri_2
overwrite:
有:覆蓋原來的資料,只保留新上傳的資料。
無:在原來的目錄下,在增加一個數據檔案。
partition:
有:增加到相應的分割槽中
無:該表不是分割槽表
2°、從其他表中裝載
insert <into|overwrite> table tblName select columns... from otherTblName;
關於overwrite的含義和上述是一致的。
唯一一點需要說明的是:
tblName表中的欄位要和後面select查詢的欄位要保持一致!!!
注意:有一個特殊的地方就是,hive中存在著同一份資料多種處理
Hive本身提供了一個獨特的語法,她可以從一個數據源產生多個數據聚合,而無需每次聚合都要重新掃描一次。對於大的資料輸入集來說,這個優化可以節約非常可觀的時間。
例如,下面這個兩個查詢都會從原表history讀取資料,然後倒入到2個不同的表中:
hive> insert overwrite table sales
> select * from history where dt=’2016-01-16’;
hive> insert overwrite table credits
> select * from history where dt=’2016-01-17’;
上面的查詢,語法是正確的,不過執行效率低下。而如下這個查詢可以達到同樣的目的,卻只需要掃描history表一次就可以了:
hive> from history
> insert overwrite sales select * where dt=’2016-01-16’
> insert overwrite credits select * where dt=’2016-01-17’;
3°、通過動態分割槽裝載資料
如果我們表的分割槽建立非常多的話,對於我們裝載資料是一件非常麻煩的事,Hive提供動態分割槽來解決這個問題。
可以基於查詢引數推斷出需要建立的分割槽名稱,相比的分割槽都是靜態的,這裡就稱之為動態的分割槽。
怎麼來弄呢?
INSERT overwrite TABLE t3 PARTITION(province='gs', city) 
SELECT t.province, t.city FROM temp t WHERE t.province='gs';
說明一下:靜態分割槽必須出現在動態分割槽之前!!!
我想連province='gs'都省了?
報錯了,需要我們開啟動態分割槽的支援
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
set hive.exec.max.dynamic.partitions.pernode=1000;
INSERT overwrite TABLE t3 PARTITION(province, city) 
SELECT t.province, t.city FROM temp t;
經驗說明一點:
在建立分割槽的時候,最好不要建立過多的分割槽,如果分割槽過多的話,查詢也是非常的慢的,就像在window下一個資料夾下面的檔案過多會對我們的使用造成非常的不便的。
那麼hive能支援多大的分割槽數呢,可以使用命令
set hive.exec.max.dynamic.partitions獲取
遇到的問題:
Dynamic partition cannot be the parent of a static partition 'year'
載入資料的時候和分割槽的順序有關聯,動態分割槽不能作為靜態的父目錄
Cannot insert into target table because column number/types are different 'school': Table insclause-0 has 3 columns, but query has 4 columns.
兩張表的結構是相似的,插入的時候欄位發生衝突了,需要加表的別名來區分。 
4、建立表的同時裝載資料
和之前建立檢視的時候的語法非常相似,把view改成table就可以
eg.create table newTblName as select columns from other_tblName;
==========================================================================================
4、資料的匯出
這個是資料裝載的反向過程,有兩種方式
1°、在hdfs的直接上操作
hadoop fs -cp src_uri dest_uri
2°、在終端使用directory
insert overwrite [local] directory 'linux_fs_path' select ...from... where ...;
==========================================================================================
5、本地模式
之前有些hql語句的執行最後轉化為了mr,但是執行的過程非常的慢,如何提高執行效率呢?使用本地模式。
需要開啟本地模式:
set hive.exec.mode.local.auto=true;
再去執行相同的hql時,會發現速度提高很多。
但是,本地模式主要用來做除錯,不能配置到hive-site.xml中,因為本地模式,會只在當前機器上
執行mr,但是如果資料量一大,這樣會累垮我們的單臺節點的。
==========================================================================================