1. 程式人生 > >hive的資料儲存淺談

hive的資料儲存淺談

一、導言:

     Hive是基於Hadoop分散式檔案系統,它的資料儲存在Hadoop分散式檔案系統中。Hive本身是沒有專門的資料儲存格式,也沒有為資料建立索引,只需要在建立標的時候告訴Hive資料中的列分隔和行分隔符,Hive就可以解析資料。所以往hive裡匯入資料只是簡單的將資料移動到表所在的目錄中;Hive是建立在 Hadoop 上的資料倉庫基礎構架。它提供了一系列的工具,可以用來進行資料提取轉化載入(ETL),這是一種可以儲存、查詢和分析儲存在 Hadoop 中的大規模資料的機制。Hive 定義了簡單的類 SQL 查詢語言,稱為 HQL,它允許熟悉 SQL 的使用者查詢資料。同時,這個語言也允許熟悉 MapReduce 開發者的開發自定義的 mapper 和 reducer 來處理內建的 mapper 和 reducer 無法完成的複雜的分析工作。
Hive 沒有專門的資料格式。 Hive 可以很好的工作在 Thrift 之上,控制分隔符,也允許使用者指定資料格式

二、hive的資料型別

    Hive的資料分為表資料和元資料,表資料是Hive中表格(table)具有的資料;而元資料是用來儲存表的名字,表的列和分割槽及其屬性,表的屬性(是否為外部表等),表的資料所在目錄等。下面分別來介紹。

三、hive資料儲存

Hive是基於Hadoop分散式檔案系統的,它的資料儲存在Hadoop分散式檔案系統中。

1、表:Hive中的表和關係型資料庫中的表在概念上很類似,每個表在HDFS中都有相應的目錄用來儲存表的資料,這個目錄可以通過${HIVE_HOME}/conf/hive-site.xml配置檔案中的 hive.metastore.warehouse.dir屬性來配置,這個屬性預設的值是/user/hive/warehouse(這個目錄在 HDFS上),我們可以根據實際的情況來修改這個配置。如果我有一個表wyp,那麼在HDFS中會建立/user/hive/warehouse/wyp 目錄(這裡假定hive.metastore.warehouse.dir配置為/user/hive/warehouse);wyp表所有的資料都存放在這個目錄中。這個例外是外部表。

2、外部表:Hive中的外部表和表很類似,但是其資料不是放在自己表所屬的目錄中,而是存放到別處,這樣的好處是如果你要刪除這個外部表,該外部表所指向的資料是不會被刪除的,它只會刪除外部表對應的元資料;而如果你要刪除表,該表對應的所有資料包括元資料都會被刪除。

3、分割槽:在Hive中,表的每一個分割槽對應表下的相應目錄,所有分割槽的資料都是儲存在對應的目錄中。比如wyp 表有dt和city兩個分割槽,則對應dt=20131218,city=BJ對應表的目錄為/user/hive/warehouse /dt=20131218/city=BJ,所有屬於這個分割槽的資料都存放在這個目錄中。

4、桶:對指定的列計算其hash,根據hash值切分資料,目的是為了並行,每一個桶對應一個檔案(注意和分割槽的區別)。比如將wyp表id列分散至16個桶中,首先對id列的值計算hash,對應hash值為0和16的資料儲存的HDFS目錄為:/user /hive/warehouse/wyp/part-00000;而hash值為2的資料儲存的HDFS 目錄為:/user/hive/warehouse/wyp/part-00002。

盜個圖:


表是在資料庫下面,而表裡面又要分割槽、桶、傾斜的資料和正常的資料等;分割槽下面也是可以建立桶的。

四、Hive的元資料

Hive中的元資料包括表的名字,表的列和分割槽及其屬性,表的屬性(是否為外部表等),表的資料所在目錄等。 由於Hive的元資料需要不斷的更新、修改,而HDFS系統中的檔案是多讀少改的,這顯然不能將Hive的元資料儲存在HDFS中。而是存放在傳統的RDBMS中,典型的如mysql,derby等,這裡我們以mysql為元資料庫。可以通過以下配置來修改Hive元資料的儲存方式。

<property> 
  <name>javax.jdo.option.ConnectionURL</name> 
  <value>jdbc:mysql://localhost:3306/hive_hdp?characterEncoding=UTF-8 
                    &createDatabaseIfNotExist=true</value> 
  <description>JDBC connect string for a JDBC metastore</description> 
</property> 
  
<property> 
  <name>javax.jdo.option.ConnectionDriverName</name> 
  <value>com.mysql.jdbc.Driver</value> 
  <description>Driver class name for a JDBC metastore</description> 
</property> 
  
<property> 
  <name>javax.jdo.option.ConnectionUserName</name> 
  <value>root</value> 
  <description>username to use against metastore database</description> 
</property> 
  
<property> 
  <name>javax.jdo.option.ConnectionPassword</name> 
  <value>123456</value> 
  <description>password to use against metastore database</description> 
</property> 
你還需要將相應資料庫的啟動複製到${HIVE_HOME}/lib目錄中,這樣才能將元資料儲存在對應的資料庫中。

五、Hive的儲存和解析

這部分詳情可以參見官方文件:點選開啟連結

1.CREATE TABLE

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
  [(col_name data_type [COMMENT col_comment], ...)]
  [COMMENT table_comment]
  [PARTITIONED BY (col_name data_type
    [COMMENT col_comment], ...)]
  [CLUSTERED BY (col_name, col_name, ...)
  [SORTED BY (col_name [ASC|DESC], ...)]
  INTO num_buckets BUCKETS]
  [ROW FORMAT row_format]
  [STORED AS file_format]
  [LOCATION hdfs_path]
CREATE TABLE 建立一個指定名字的表。如果系統名字的表已經存在,則操作異常;使用者可以使用 IF NOT EXIST選項來忽略這個異常。

EXTERNAL建立外部表

example1:

我們先來看下hive中如何建表,並通過分析建表語句瞭解hive中資料的儲存解析方式

create table tutorial ( 
    name string,                          --string型別欄位name
    number int,	                          -- int型別欄位number
    resource array<string>,                    -- string陣列型別欄位
    detail map<string, int>)                  -- 字典型別(key為字串,value為整型)
partitioned by (dt string)                      -- 按dt分割槽,dt型別為string
row format delimited fields terminated by '\t'	      -- 指定列分隔符為tab
collection items terminated by ','	        	-- 指定陣列中欄位分隔符為逗號
map keys terminated by ':' ;	            	-- 指定字典中KV分隔符為冒號
根據上面的建表語句,對應的資料應該長這樣:

balabala2 222 str1,str2,str3 a:1,b:2,c:3

balabala3 333 str4,str5,str6 d:4,e:5,f:6
....
hive在讀取資料時,首先根據TAB對列進行分隔,得到name, number, source, detail,name和number不用繼續處理,可直接使用

source和detail屬於複雜資料型別,hive需要再次進行解析:根據逗號分隔source,detail,再根據冒號分隔detail中每一項的key和value

ps. 這其中涉及到一個概念:讀時模式 和 寫時模式

讀時模式:載入資料時進行資料檢驗(hive)

寫時模式:寫入資料時對照模式進行檢查(傳統RDBMS)

2.hive的幾種檔案儲存格式

hive檔案儲存格式包括以下幾類:
TEXTFILE
SEQUENCEFILE
RCFILE
自定義格式

1.TEXTFILE

預設格式,資料不做壓縮,磁碟開銷大,資料解析開銷大。可結合Gzip、Bzip2使用(系統自動檢查,執行查詢時自動解壓),但使用這種方式,hive不會對資料進行切分,從而無法對資料進行並行操作。
example2:
> create table test1(str STRING)  
> STORED AS TEXTFILE;   
OK  
Time taken: 0.786 seconds  
#寫指令碼生成一個隨機字串檔案,匯入檔案:  
> LOAD DATA LOCAL INPATH '/home/work/data/test.txt' INTO TABLE test1;  
Copying data from file:/home/work/data/test.txt  
Copying file: file:/home/work/data/test.txt  
Loading data to table default.test1  
OK  
Time taken: 0.243 seconds 

2.SEQUENCEFILE

SequenceFile是Hadoop API提供的一種二進位制檔案支援,其具有使用方便、可分割、可壓縮的特點。SequenceFile支援三種壓縮選擇:NONE, RECORD, BLOCK。 Record壓縮率低,一般建議使用BLOCK壓縮。


> create table test3(str STRING)  
> STORED AS RCFILE;  
OK  
Time taken: 0.184 seconds  
>  INSERT OVERWRITE TABLE test3 SELECT * FROM test1;

3.自定義格式

當用戶的資料檔案格式不能被當前 Hive 所識別的時候,可以自定義檔案格式。使用者可以通過實現inputformat和outputformat來自定義輸入輸出格式,參考程式碼:
.\hive-0.8.1\src\contrib\src\java\org\apache\hadoop\hive\contrib\fileformat\base64
example4:
> create table test4(str STRING)  
> stored as  
> inputformat 'org.apache.hadoop.hive.contrib.fileformat.base64.Base64TextInputFormat'  
> outputformat 'org.apache.hadoop.hive.contrib.fileformat.base64.Base64TextOutputFormat'; 
$ cat test1.txt 
aGVsbG8saGl2ZQ==
aGVsbG8sd29ybGQ=
aGVsbG8saGFkb29w
test1檔案為base64編碼後的內容,decode後資料為:
hello,hive
hello,world
hello,hadoop
load資料並查詢:
hive> LOAD DATA LOCAL INPATH '/home/work/test1.txt' INTO TABLE test4;   
Copying data from file:/home/work/test1.txt  
Copying file: file:/home/work/test1.txt  
Loading data to table default.test4  
OK  
Time taken: 4.742 seconds  
hive> select * from test4;  
OK  
hello,hive  
hello,world  
hello,hadoop  
Time taken: 1.953 seconds
相比TEXTFILE和SEQUENCEFILE,RCFILE由於列式儲存方式,資料載入時效能消耗較大,但是具有較好的壓縮比和查詢響應。資料倉庫的特點是一次寫入、多次讀取,因此,整體來看,RCFILE相比其餘兩種格式具有較明顯的優勢。