案例詳解__HIVE中內部表、外部表、分區表和分桶表

目錄
一、Hive建表語法
二、內部表外部表
三、分區表
四、分桶表

Hive在建表時可指定內部表、外部表、分區表和分桶表,所以在學習這四種表之前,先一起了解Hive建表語法

一、Hive建表語法

Hive建表方式共有三種:直接建表法、查詢建表法、like建表法,下面講解直接建表法

’[]’ 表示可選,’|’ 表示二選一

創建表的語句:
Create [EXTERNAL] TABLE [IF NOT EXISTS] table_name 
//EXTERNAL 關鍵字可以讓用戶創建一個外部表,如果不指定關鍵字EXTERNAL則爲內部表
//如:create table IF NOT EXISTS test_bucket
[(col_name data_type [COMMENT col_comment], ...)] 
//col_nam表字段,data_type字段類型,[COMMENT col_comment]字段註釋 , ...爲其他字段
//如:(word string,num bigint )
[COMMENT table_comment] 
//表註釋,COMMENT關鍵字,table_comment表解釋具體內容
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)] 
//PARTITIONED BY分區
[CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC],...)]INTO num_buckets BUCKETS]
//分桶,通過 clustered by(字段名) into bucket_num buckets 分桶,意思是根據字段名分成bucket_num個桶
//如:clustered by(id) into 4 buckets
[ROW FORMAT row_format] 
//加載數據文件到hive表時,數據文件字段於字段的分隔符
//如:row format delimited fields terminated by '\t'
[STORED AS file_format] 
[LOCATION hdfs_path]
//指定表存放的HDFS位置,如果不指定存放在默認路徑,內部表默認路徑/user/hive/warehouse
建表語句解釋:
  • CREATE TABLE 創建一個指定名字的表。

  • EXTERNAL 關鍵字可以讓用戶創建一個外部表,無EXTERNAL 關鍵字則爲內部表。在刪除表的時候,內部表的元數據和數據會被一起刪除,而外部表只刪除元數據,不刪除數據。

  • 有分區的表可以在創建的時候使用 PARTITIONED BY 語句。一個表可以擁有一個或者多個分區,每一個分區單獨存在一個目錄下。

案例:
//01-創建orders_part外部表
create  EXTERNAL table orders_part(
order_id string comment '訂單編號',
user_id string comment '客戶號',
order_number string  comment '訂單數量',
order_date string comment '下單時間'
)
comment '測試_創建orders_part表'
partitioned by(order_date string)
row format delimited fields terminated by ','

//02-創建分桶表
create table test_bucket (
id int comment 'ID', 
name string comment '名字'
)
comment '測試分桶'
clustered by(id) into 4 buckets
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' ;

二、內部表外部表

通過建表語句、location位置、刪除表三方面來學習外部表,內部表

1、建表語句

1.1、內部表
平時創建的普通表爲內部表

create table `test_internal` (
id string comment 'ID', 
name string comment '名字'
)
comment '測試內部表'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' ;

1.2、外部表
external關鍵字的爲外部表

create external table `test_external` (
id string comment 'ID', 
name string comment '名字'
)
comment '測試外部表'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' ;

僅從建表語句上看,內部表和外部表的區別爲是否帶有external關鍵字

2、location

網上很多博客寫的外部表建表語句中都帶有location關鍵字,我這裏單獨分開來寫。[我參考的是一個博主的文章]

  • 其實不管是內部表還是外部表可以加location關鍵字指定hive表的存儲路徑,當然也可以不加,從這點看是無區別的。

  • 如果不加location那麼不管是內部表還是外部表會在默認的hive配置的hdfs路徑下下新建一個和表名相同的文件夾。內部表默認存放路徑:/user/hive/warehouse

  • 如果加了location指定另外的文件夾,那麼在查詢時,該文件夾下對應的數據會加載到hive表裏。

如果不理解上面文字描述可以看下面案例

案例:
01、準備數據

將數據上傳到HDFS

//data.txt 數據
001,張三
002,李四
003,王五
hadoop fs -mkdir -p /tmp/hive_test/internal_location //創建Hdfs目錄
hadoop fs -mkdir -p /tmp/hive_test/external_location
hadoop fs -put data.txt /tmp/hive_test/internal_location  //上傳數據到HDFS
hadoop fs -put data.txt /tmp/hive_test/external_location //上傳數據到HDFS文件夾

02、建表

內部表

create table IF NOT EXISTS test_internal_location (
id string comment 'ID', 
name string comment '名字'
)
comment '測試內部表location'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' 
location '/tmp/hive_test/internal_location';

外部表

create external table   IF NOT EXISTS test_external_location (
id string comment 'ID', 
name string comment '名字'
)
comment '測試外部表location'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' 
location '/tmp/hive_test/external_location';

說明:hdfs 文件夾及對應下的數據和建表語句沒有先後順序,建表在前和在後都可以把數據加載出來,如果先建表的話,對應的文件夾如果不存在,則會自動建立文件夾。

3、刪除表

內部表和外部表的區別主要體現在刪除表,將上面建立的2個表都刪掉。

drop table test_internal_location;
drop table test_external_location;

看一下對應的hdfs路徑有啥變化


發現外部表external_location文件夾存在,而內部表文件夾沒了,這也就是內部表和外部表的區別

內部表刪除表時,對應的hdfs的路徑下的文件會刪掉;外部表刪除表時,對應的HDFS的路徑下的文件則不會刪掉。

4、內部表外部表—總結

(1) 建表:帶有external關鍵字爲外部表,否則爲內部表
(2) location:內部表和外部表建表時都可以自己指定location
(3) 刪除表:外部表不會刪除對應的數據,只會刪除元數據信息,內部表則會刪除元數據信息和對應的數據。

參考文章:Hive內部表和外部表,看了這個博主寫的兩篇文章,寫得真的很好很好。

三、分區表

分區表一般在數據量比較大,且有明確的分區字段時使用,這樣用分區字段作爲查詢條件查詢效率會比較高。Hive分區分爲靜態分區動態分區

1、爲什麼出現分區表?

假設有海量的數據保存在hdfs的某一個hive表名對應的目錄下,使用hive進行操作的時候,往往會搜索這個目錄下的所有的文件,這時會非常耗時。(hive表對應hdfs目錄下的文件數據都會被加載到hive表中)

如果我們知道這些數據的某些特徵,然後使用Hive進行操作的時候,就可以在where子句種對這些特徵進行過濾,那麼對數據的操作就會在符合條件子目錄下進行,其他不符合條件目錄下的內容就不會被讀取

在數據量非常大的時候,這樣節省大量的時間,這種把表種的數據分散到子目錄下的方式就是分區表。



下面我們還是通過實戰來學習分區表

案例

2、創建分區表

靜態分區和動態分區的建表語句是一樣的

create table test_partition (
name string comment '名字',
age int comment '年齡'
)
comment '測試分區'
partitioned by (provice string comment '省',city string comment '城市')
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' ;

用partitioned by指定創建的分區,多個分區意味着多級目錄。

創建之後hdfs上的目錄結構並不會立即發生變化,因爲此時表中還沒有數據,往表中插入數據之後,會發現在表名對應的目錄下,會多出兩級目錄。

3、插入語句

靜態分區和動態分區的插入數據的語法是不一樣的,下面講解靜態分區
想學習動態分區可看這篇文章hive使用動態分區插入數據詳解

3.1 靜態分區

靜態分區是在語句中指定分區字段爲某個固定值

3.1.1 靜態分區加載數據-INSERT INTO語法
insert into table test_partition partition(provice = "hebei",city = "baoding") values ('張三',20);
insert into table test_partition partition(provice = "hebei",city = "baoding") values ('張三',20);
insert into table test_partition partition(provice = "hebei",city = "baoding") values ('李四',20);

insert into table test_partition partition(provice = "hebei",city = "handan") values ('張三',20);
insert into table test_partition partition(provice = "hebei",city = "handan") values ('張三',20);
insert into table test_partition partition(provice = "hebei",city = "handan") values ('李四',20);
3.1.2 靜態分區加載數據-LOAD DATA方法

data4.txt

張三,23
李四,23
王五,23

加載本地文件到hive表中

load data local inpath '/home/study/data4.txt' into table test_partition partition (provice = "hebei",city = "handan");
load data local inpath '/home/study/data4.txt' into table test_partition partition (provice = "hebei",city = "handan");
load data local inpath '/home/study/data4.txt' into table test_partition partition (provice = "sichuan",city = "chengdu");

3.1.3 查看數據

hive的倉庫路徑: /user/hive/warehouse
數據庫名稱: myhive.db myhive
表名: test_partition
分區字段名:provice,city

總結:

  • (1) 分區表的意思,其實想明白了就很簡單。就是在系統上建立文件夾,把分類數據放在不同文件夾下面,加快查詢速度。

  • (2) 關鍵點1:partitioned by (provice String,city string); 創建表格時,指明瞭這是一個分區表。將建立雙層目錄,第一次目錄的名字和第二層目錄名字規則
    PARTITIONED BY子句中定義列,是正式的列,成爲分區列。但是數據文件中並沒有這些值,僅代表目錄

  • (3) 關鍵點2:partition (provice = "hebei",city = "handan"); 上傳數據時,把數據分別上傳到不同分區中。也就是分別放在不同的子目錄下。

參考文章1:Hive分區表學習總結
參考文章2:hive使用動態分區插入數據詳解
參考文章3:HIVE-分區表詳解以及實例

四、分桶表

其實分區和分桶這兩個概念對於初學者來說是比較難理解的,要想更好的學習分桶表,看文章的同時還需要自己操作纔行。下面我們通過實操來學習分桶表[可能剛看着代碼有點迷惑,不過做到後面就理解了]

也可以像我這樣學習:看文章+實操+寫文章總結,很多知識點我按這樣學習後基本上不會忘記。

1、分桶簡介?

分桶規則:桶是通過對指定列進行哈希計算來實現的,對分桶字段值進行哈希,哈希值除以桶的個數求餘,餘數決定了該條記錄在哪個桶中,也就是餘數相同的在一個桶中。
優點:1、提高join查詢效率 2、提高抽樣效率

2、分桶操作

2.1、創建桶表:

通過 clustered by(字段名) into bucket_num buckets 分桶,意思是根據字段名分成bucket_num個桶

create table test_bucket (
id int comment 'ID', 
name string comment '名字'
)
comment '測試分桶'
clustered by(id) into 4 buckets
-- 注意分桶字段只能是建表中已有的字段,
-- 而分區表的字段必須是建表中沒有的字段
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' ;

2.2、設置Hive的分桶開關

打開Hive客戶端,並在會話終端開啓Hive分桶的開關:set hive.enforce.bucketing=true;(此設置爲臨時設置,一旦退出會話終端,再打開就會恢復默認設置false)

set hive.enforce.bucketing=true;  ///強制分桶

此開關打開之後,會自動根據bucket(桶)個數自動分配Reduce task個數,Reduce個數與bucket個數一致。(此外,Reduce的個數還可以通過mapred.reduce.tasks進行設置,但是這方法不推薦在Hive分桶中使用)

2.2.3、load data方法插入數據到分桶表

buckt_data.txt

1,name1
2,name2
3,name3
4,name4
5,name5
6,name6
7,name7
8,name8
9,name9

load data 插入數據到分桶表

load data local inpath '/home/study/buckt_data.txt' into table test_bucket ;


我們看到雖然設置了強制分桶,但實際test_bucket 表下面只有一個test_bucket 一個文件。直接load data不會分桶的效果,這樣和不分桶一樣,在HDFS上只有一個文件。需要藉助中間表才能實現

2.2.3、借用中間表insert into方法插入數據到分桶表

創建中間表

create table test (
id int comment 'ID', 
name string comment '名字'
)
comment '測試分桶中間表'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' ;

先將數據load到中間表

load data local inpath '/home/study/buckt_data.txt' into table test;

通過下面insert into的語句,將中間表的數據插入到分桶表中,這樣會產生四個文件。

insert into test_bucket select * from test;

從上面圖片可以看見:
(1) 是以文件的形式存在的,而不是像分區那樣以文件夾的形式存在。
(2) 除以4餘數相同的確實在一個文件裏,也就是在一個桶中

總結:

(1) 其實桶的概念就是MapReduce的分區的概念,兩者完全相同。物理上每個桶就是目錄裏的一個文件,一個作業產生的桶(輸出文件)數量和reduce任務個數相同。
(2) 桶是按照數據內容的某個值進行分桶,把一個大文件散列稱爲一個個小文件。
(3) 這些小文件可以單獨排序。如果另外一個表也按照同樣的規則分成了一個個小文件。兩個表join的時候,就不必要掃描整個表,只需要匹配相同分桶的數據即可。效率當然大大提升。
同樣,對數據抽樣的時候,也不需要掃描整個文件。只需要對每個分區按照相同規則抽取一部分數據即可。

參考文章1:Hive分桶表學習總結
參考文章2:HIVE-分桶表的詳解和創建實例
參考文章3:Hive分桶表的使用場景以及優缺點分析,想了解概念看該篇文章

關於HIVE中內部表、外部表、分區表和分桶表就總結完了,後期還得繼續努力學習呀.問題還是得一個一個的解決.加油啦~~~
做仰臥起坐去了,週末愉快啦.
這個冬天真冷

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章