轉載自:http://www.cnblogs.com/sharpxiajun/archive/2013/06/03/3114560.html
hive支持兩種數據類型:基本和複雜數據類型
基本包括數值型(tinyint/smallint/int/bigint/flout/double)、布爾型(true/false)、字符串型(string)、binary、timestamp、decimal、char、varchar、datehive是用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的數據。