大資料時代的技術hive:hive的資料型別和資料模型

caixingyun發表於2017-02-22

來自:http://www.cnblogs.com/sharpxiajun/archive/2013/06/03/3114560.html

在上篇文章裡,我列舉了一個簡單的hive操作例項,建立了一張表test,並且向這張表載入了資料,這些操作和關聯式資料庫操作類似,我們常把hive和關聯式資料庫進行比較,也正是因為hive很多知識點和關聯式資料庫類似。

  關聯式資料庫裡有表(table),分割槽,hive裡也有這些東西,這些東西在hive技術裡稱為hive的資料模型。今天本文介紹hive的資料型別,資料模型以及檔案儲存格式。這些知識大家可以類比關聯式資料庫的相關知識。

  首先我要講講hive的資料型別。

  Hive支援兩種資料型別,一類叫原子資料型別,一類叫複雜資料型別。

  原子資料型別包括數值型、布林型和字串型別,具體如下表所示:

基本資料型別

型別

描述

示例

TINYINT

1個位元組(8位)有符號整數

1

SMALLINT

2位元組(16位)有符號整數

1

INT

4位元組(32位)有符號整數

1

BIGINT

8位元組(64位)有符號整數

1

FLOAT

4位元組(32位)單精度浮點數

1.0

DOUBLE

8位元組(64位)雙精度浮點數

1.0

BOOLEAN

true/false

true

STRING

字串

‘xia’,”xia”

 

  由上表我們看到hive不支援日期型別,在hive裡日期都是用字串來表示的,而常用的日期格式轉化操作則是通過自定義函式進行操作。

  hive是用java開發的,hive裡的基本資料型別和java的基本資料型別也是一一對應的,除了string型別。有符號的整數型別:TINYINT、SMALLINT、INT和BIGINT分別等價於java的byte、short、int和long原子型別,它們分別為1位元組、2位元組、4位元組和8位元組有符號整數。Hive的浮點資料型別FLOAT和DOUBLE,對應於java的基本型別float和double型別。而hive的BOOLEAN型別相當於java的基本資料型別boolean。

  對於hive的String型別相當於資料庫的varchar型別,該型別是一個可變的字串,不過它不能宣告其中最多能儲存多少個字元,理論上它可以儲存2GB的字元數。

  Hive支援基本型別的轉換,低位元組的基本型別可以轉化為高位元組的型別,例如TINYINT、SMALLINT、INT可以轉化為FLOAT,而所有的整數型別、FLOAT以及STRING型別可以轉化為DOUBLE型別,這些轉化可以從java語言的型別轉化考慮,因為hive就是用java編寫的。當然也支援高位元組型別轉化為低位元組型別,這就需要使用hive的自定義函式CAST了。

  複雜資料型別包括陣列(ARRAY)、對映(MAP)和結構體(STRUCT),具體如下表所示:

複雜資料型別

型別

描述

示例

ARRAY

一組有序欄位。欄位的型別必須相同

Array(1,2)

MAP

一組無序的鍵/值對。鍵的型別必須是原子的,值可以是任何型別,同一個對映的鍵的型別必須相同,值得型別也必須相同

Map(‘a’,1,’b’,2)

STRUCT

一組命名的欄位。欄位型別可以不同

Struct(‘a’,1,1,0)

 

下面我們看看hive使用複雜資料型別的例項,建表:

Create table complex(col1 ARRAY<INT>,
Col2 MAP<STRING,INT>,
Col3 STRUCT<a:STRING,b :INT,c:DOUBLE>);

  

查詢語句:

Select col1[0],col2[‘b’],col3.c from complex;

  

  接下來我們來看看hive的資料模型,hive的資料模型包括:database、table、partition和bucket。下面我將一一論述這四種資料模型。

1.Database:相當於關聯式資料庫裡的名稱空間(namespace),它的作用是將使用者和資料庫的應用隔離到不同的資料庫或模式中,該模型在hive 0.6.0之後的版本支援,hive提供了create database dbname、use dbname以及drop database dbname這樣的語句。

2.表(table):hive的表邏輯上由儲存的資料和描述表格中的資料形式的相關後設資料組成。表儲存的資料存放在分散式檔案系統裡,例如HDFS,後設資料儲存在關聯式資料庫裡,當我們建立一張hive的表,還沒有為表載入資料的時候,該表在分散式檔案系統,例如hdfs上就是一個資料夾(檔案目錄)。Hive裡的表友兩種型別一種叫託管表,這種表的資料檔案儲存在hive的資料倉儲裡,一種叫外部表,這種表的資料檔案可以存放在hive資料倉儲外部的分散式檔案系統上,也可以放到hive資料倉儲裡(注意:hive的資料倉儲也就是hdfs上的一個目錄,這個目錄是hive資料檔案儲存的預設路徑,它可以在hive的配置檔案裡進行配置,最終也會存放到後設資料庫裡)。

下面是建立託管表的例項語句:

 

Create table tuoguan_tbl (flied string);
Load data local inpath ‘home/hadoop/test.txt’ into table tuoguan_tbl;

  

外部表建立的例項:

Create external table external_tbl (flied string)
    Location  ‘/home/hadoop/external_table’;
Load data local inpath ‘home/hadoop/test.txt’ into table external_tbl;

  

  大家看到了建立外部表時候table之前要加關鍵字external,同時還要用location命令指定檔案儲存的路徑,如果不使用locaction資料檔案也會放置到hive的資料倉儲裡。

  這兩種表在使用的區別主drop命令上,drop是hive刪除表的命令,託管表執行drop命令的時候,會刪除後設資料和儲存的資料,而外部表執行drop命令時候只刪除後設資料庫裡的資料,而不會刪除儲存的資料。另外我還要談談表的load命令,hive載入資料時候不會對後設資料進行任何檢查,只是簡單的移動檔案的位置,如果原始檔格式不正確,也只有在做查詢操作時候才能發現,那個時候錯誤格式的欄位會以NULL來顯示。

 3.分割槽(partition):hive裡分割槽的概念是根據“分割槽列”的值對錶的資料進行粗略劃分的機制,在hive儲存上就體現在表的主目錄(hive的表實際顯示就是一個資料夾)下的一個子目錄,這個資料夾的名字就是我們定義的分割槽列的名字,沒有實際操作經驗的人可能會認為分割槽列是表的某個欄位,其實不是這樣,分割槽列不是表裡的某個欄位,而是獨立的列,我們根據這個列儲存表的裡的資料檔案。使用分割槽是為了加快資料分割槽的查詢速度而設計的,我們在查詢某個具體分割槽列裡的資料時候沒必要進行全表掃描。下面我就舉一個分割槽使用的例項:

建立分割槽:

Create table logs(ts bigint,line string)
Partitioned by (dt string,country string);

  

 

載入資料:

Local data local inpath ‘/home/hadoop/par/file01.txt’ into table logs partition (dt=’2012-06-02’,country=’cn’);

  

 

在hive資料倉儲裡實際儲存的路徑如下所示:

/user/hive/warehouse/logs/dt=2013-06-02/country=cn/file1.txt
/user/hive/warehouse/logs/dt=2013-06-02/country=cn/file2.txt
/user/hive/warehouse/logs/dt=2013-06-02/country=us/file3.txt
/user/hive/warehouse/logs/dt=2013-06-02/country=us/file4.txt

  

 

我們看到在表logs的目錄下有了兩層子目錄dt=2013-06-02和country=cn

查詢操作:

Select ts,dt,line  from logs where country=’cn’,

  

這個時候我們的查詢操作只會掃描file1.txt和file2.txt檔案。

4.桶(bucket):上面的table和partition都是目錄級別的拆分資料,bucket則是對資料來源資料檔案本身來拆分資料。使用桶的表會將源資料檔案按一定規律拆分成多個檔案,要使用bucket,我們首先要開啟hive對桶的控制,命令如下:

set hive.enforce.bucketing = true

  

下面這段文字是我引用部落格園裡風生水起的博文:

示例:
建臨時表student_tmp,並匯入資料:
hive> desc student_tmp;        
OK
id      int
age     int
name    string
stat_date       string
Time taken: 0.106 seconds
hive> select * from student_tmp;
OK
1       20      zxm     20120801
2       21      ljz     20120801
3       19      cds     20120801
4       18      mac     20120801
5       22      android 20120801
6       23      symbian 20120801
7       25      wp      20120801
Time taken: 0.123 seconds
 
建student表:
hive>create table student(id INT, age INT, name STRING)
       >partitioned by(stat_date STRING)
       >clustered by(id) sorted by(age) into 2 bucket
       >row format delimited fields terminated by ',';
 
設定環境變數:
       >set hive.enforce.bucketing = true;
 
插入資料:
 
       >from student_tmp
       >insert overwrite table student partition(stat_date="20120802")
       >select id,age,name where stat_date="20120801" sort by age;
 
檢視檔案目錄:
$ hadoop fs -ls /user/hive/warehouse/studentstat_date=20120802/
Found 2 items
-rw-r--r--   1 work supergroup         31 2012-07-31 19:52 /user/hive/warehouse/student/stat_date=20120802/000000_0
-rw-r--r--   1 work supergroup         39 2012-07-31 19:52 /user/hive/warehouse/student/stat_date=20120802/000001_0

  

  物理上,每個桶就是表(或分割槽)目錄裡的一個檔案,桶檔案是按指定欄位值進行hash,然後除以桶的個數例如上面例子2,最後去結果餘數,因為整數的hash值就是整數本身,上面例子裡,欄位hash後的值還是欄位本身,所以2的餘數只有兩個0和1,所以我們看到產生檔案的字尾是*0_0和*1_0,檔案裡儲存對應計算出來的後設資料。

  Hive的桶,我個人認為沒有特別的場景或者是特別的查詢,我們可以沒有必要使用,也就是不用開啟hive的桶的配置。因為桶運用的場景有限,一個是做map連線的運算,我在後面的文章裡會講到,一個就是取樣操作了,下面還是引用風生水起博文裡的例子:

檢視sampling資料:
hive> select * from student tablesample(bucket 1 out of 2 on id);                                                                              
Total MapReduce jobs = 1
Launching Job 1 out of 1
.......
OK
4       18      mac     20120802
2       21      ljz     20120802
6       23      symbian 20120802
Time taken: 20.608 seconds
 
tablesample是抽樣語句,語法:TABLESAMPLE(BUCKET x OUT OF y)
y必須是table總bucket數的倍數或者因子。hive根據y的大小,決定抽樣的比例。例如,table總共分了64份,當y=32時,抽取 (64/32=)2個bucket的資料,當y=128時,抽取(64/128=)1/2個bucket的資料。x表示從哪個bucket開始抽取。例 如,table總bucket數為32,tablesample(bucket 3 out of 16),表示總共抽取(32/16=)2個bucket的資料,分別為第3個bucket和第(3+16=)19個bucket的資料。

  

  好了,今天就寫到這裡了,明天要上班不能在加班寫文章了。這篇博文的內容並沒有寫完(hive儲存格式沒有寫),因為這個章節的知識非常重要是理解hive的關鍵,所以要講的細點,明天我爭取寫完hive儲存格式的文章,後天也就是本週二,我將為我們技術部門介紹hive的相關技術,寫博文算是我的預演了。

  最後我要講一下自己對大資料技術的看法,我覺得大資料技術是一個跨時代的技術,是網際網路技術的未來,也是雲端計算的未來,它的深入發展不僅僅是資料處理上,也會改變整個網際網路技術的生態鏈,包括我們使用的技術和開發語言,很慶幸親身經歷著整個偉大時代的變革,我也要展開雙臂迎接這個大時代的到來。


相關文章