溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

hive存儲(chǔ)處理器(StorageHandlers)以及hive與hbase整合

發(fā)布時(shí)間:2020-06-19 20:46:25 來(lái)源:網(wǎng)絡(luò) 閱讀:5563 作者:璽感 欄目:關(guān)系型數(shù)據(jù)庫(kù)

 此篇文章基于hive官方英文文檔翻譯,有些不好理解的地方加入了我個(gè)人的理解,官方的英文地址為:

1.https://cwiki.apache.org/confluence/display/Hive/StorageHandlers

2.https://cwiki.apache.org/confluence/display/Hive/HBaseIntegration

 

存儲(chǔ)處理器介紹

通過(guò)HIVE存儲(chǔ)處理器,不但可以讓hive基于hbase實(shí)現(xiàn),還可以支持cassandra JDBC MongoDB 以及 Google Spreadsheets 

HIVE存儲(chǔ)器的實(shí)現(xiàn)原理基于HIVE以及Hadoop的可擴(kuò)展性實(shí)現(xiàn):

輸入格式化(input formats

輸出格式化(output formats

序列化/反序列化包(serialization/deserialization librarises 

除了依據(jù)以上可擴(kuò)展性,存儲(chǔ)處理器還需要實(shí)現(xiàn)新的元數(shù)據(jù)鉤子接口,這個(gè)接口允許使用HIVEDDL語(yǔ)句來(lái)定義和管理hive自己的元數(shù)據(jù)以及其它系統(tǒng)的目錄(此目錄個(gè)人理解為其它系統(tǒng)的元數(shù)據(jù)目錄)

 

一些術(shù)語(yǔ):

HIVE本身有的概念:

被管理的表即內(nèi)部表(managed):元數(shù)據(jù)由hive管理,并且數(shù)據(jù)也存儲(chǔ)在hive的體系里面

外部表(external table):表的定義被外部的元數(shù)據(jù)目錄所管理,數(shù)據(jù)也存儲(chǔ)在外部系統(tǒng)中

 

hive存儲(chǔ)處理器的概念:

本地(native)表:hive不需要借助存儲(chǔ)處理器就可以直接管理和訪問(wèn)的表

非本地(non-native)表:需要通過(guò)存儲(chǔ)處理器才能管理和訪問(wèn)的表

 

內(nèi)部表 外部表 本地表 非本地表 形成交叉,就有了下面四種形式的概念定義:

被管理的本地表(managed native):通過(guò)CREATE TABLE創(chuàng)建的表

外部本地表(external native):通過(guò)CREATE EXTERNAL TABLE創(chuàng)建,但是沒(méi)有帶STORED BY子句

被管理的非本地表()managed non-native):通過(guò)CREATE TABLE 創(chuàng)建,同時(shí)有STORED BY子句,hive在元數(shù)據(jù)中存儲(chǔ)表定義,但是不創(chuàng)建任何文件(我的理解是存放數(shù)據(jù)的目錄文件,hive在定義好表結(jié)構(gòu)后會(huì)創(chuàng)建對(duì)應(yīng)的目錄來(lái)存儲(chǔ)對(duì)應(yīng)的數(shù)據(jù)),hive存儲(chǔ)處理器向存儲(chǔ)數(shù)據(jù)的系統(tǒng)發(fā)出一個(gè)請(qǐng)求來(lái)創(chuàng)建一個(gè)一致的對(duì)象結(jié)構(gòu);

外部非本地(external non-native):通過(guò)CREATE EXTERNAL TABLE創(chuàng)建,并且?guī)в?/span>STORED BY子句;hive在自己的元數(shù)據(jù)中注冊(cè)表的定義信息,并且通過(guò)調(diào)用存儲(chǔ)處理器來(lái)檢查這些注冊(cè)在hive中的信息是否與其它系統(tǒng)中原來(lái)定義的信息一致

 

通過(guò)hive創(chuàng)建表結(jié)構(gòu)的DDL語(yǔ)句:

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name

  [(col_name data_type [COMMENT col_comment], ...)]

  [COMMENT table_comment]

  [PARTITIONED BY (col_name data_type [col_comment], col_name data_type [COMMENT col_comment], ...)]

  [CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name, ...)] INTO num_buckets BUCKETS]

  [

   [ROW FORMAT row_format] [STORED AS file_format]

   | STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)]

  ]

  [LOCATION hdfs_path]

  [AS select_statement]

具體的使用樣例,會(huì)在下面詳細(xì)說(shuō)明

 

HiveHbase的整合

hiveHbase的整合通過(guò)Hbase handler jar包實(shí)現(xiàn),它的形式為hive-hbase-x.y.z.jar ,這個(gè)處理器需要依賴hadoop0.20以上版本,并且只在hadoop-0.20.x hbase-0.92.0 zookeeper-3.3.4 上進(jìn)行過(guò)測(cè)試。如果hbase版本不是0.92則需要基于你使用的版本重新編譯對(duì)應(yīng)的hive存儲(chǔ)處理器。

 

為了創(chuàng)建一張可以被hive管理的hbase的表,需要在hiveddl語(yǔ)句CREATE TABLE 后面加入語(yǔ)句STORED BY

CREATE TABLE hbase_table_1(key int, value string)

STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'

WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,cf1:val")

TBLPROPERTIES ("hbase.table.name" = "xyz");

 

Hbase.table.name屬性是可選的,用它來(lái)指定此表在hbase中的名字,這就是說(shuō),允許同一個(gè)表在hivehbase中有不同的名字。上述語(yǔ)句中,在hive中的表名叫hbase_talbe_1,hbase中,此表名叫xyz。如果不指定,兩個(gè)名字則會(huì)是相同的。

  

當(dāng)執(zhí)行完命令后,就可以在HBaseshell中看到一張新的空表,如下:

$ hbase shell

HBase Shell; enter 'help<RETURN>' for list of supported commands.

Version: 0.20.3, r902334, Mon Jan 25 13:13:08 PST 2010

hbase(main):001:0> list

xyz                                                                                                          

1 row(s) in 0.0530 seconds

hbase(main):002:0> describe "xyz"

DESCRIPTION                                                             ENABLED                              

 {NAME => 'xyz', FAMILIES => [{NAME => 'cf1', COMPRESSION => 'NONE', VE true                                 

 RSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN_MEMORY =>                                      

  'false', BLOCKCACHE => 'true'}]}                                                                           

1 row(s) in 0.0220 seconds

hbase(main):003:0> scan "xyz"

ROW                          COLUMN+CELL                                                                     

0 row(s) in 0.0060 seconds

 

上面的輸出中沒(méi)有列val的信息,雖然在建表語(yǔ)句中已經(jīng)指定了這個(gè)列名。這是因?yàn)樵?/span>hbase中只有列族的名字才會(huì)被定義在表級(jí)的元數(shù)據(jù)中,列族中的列只定義在行級(jí)別的元數(shù)據(jù)中。

 

下面的語(yǔ)句是定義怎么把數(shù)據(jù)從hive中加載進(jìn)入HBase的表,表pokeshive中已經(jīng)存在的一個(gè)表,并且表中有數(shù)據(jù)。

INSERT OVERWRITE TABLE hbase_table_1 SELECT * FROM pokes WHERE foo=98;

然后,在Hbase shell中驗(yàn)證數(shù)據(jù)是否已經(jīng)加載:

hbase(main):009:0> scan "xyz"

ROW                          COLUMN+CELL                                                                     

 98                          column=cf1:val, timestamp=1267737987733, value=val_98                           

1 row(s) in 0.0110 seconds

 

通過(guò)hive的語(yǔ)句查詢表的結(jié)果如下:

hive> select * from hbase_table_1;

Total MapReduce jobs = 1

Launching Job 1 out of 1

...

OK

98        val_98

Time taken: 4.582 seconds

 

Inserting large amounts of data may be slow due to WAL overhead; if you would like to disable this, make sure you have HIVE-1383 (as of Hive 0.6), and then issue this command before the INSERT:

set hive.hbase.wal.enabled=false;

Warning: disabling WAL may lead to data loss if an HBase failure occurs, so only use this if you have some other recovery strategy available.

 

如果想基于已經(jīng)存在的hbase表創(chuàng)建hive可訪問(wèn)的表,則需要用CREATE EXTERNAL TABLE,如下:

CREATE EXTERNAL TABLE hbase_table_2(key int, value string)

STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'

WITH SERDEPROPERTIES ("hbase.columns.mapping" = "cf1:val")

TBLPROPERTIES("hbase.table.name" = "some_existing_table");

hbase.columns.mapping屬性項(xiàng)是必須存在的,它代表的是hbase表的列族以及列的定義信息。

 

hivehbase的列匹配

有兩種SERDEPROPERTIES配置信息來(lái)控制HBase列到HIve的映射

1.hbase.columns,mapping

2.hbase.table.default.storage.type

  這個(gè)屬性可以有String和二進(jìn)制兩種類型的值,默認(rèn)是String;這個(gè)選項(xiàng)只有在hive0.9這個(gè)版本可用,     并且在早期的版本中,只有String類型可用

 

當(dāng)前列匹配使用起來(lái)顯得有點(diǎn)笨重和憋手:

1.每個(gè)hive的列,都需要在參數(shù)hbase.columns.mapping中指定一個(gè)對(duì)應(yīng)的條目(比如:ab或者:key就叫一個(gè)條目),多個(gè)列之間的條目通過(guò)逗號(hào)分隔;也就是說(shuō),如果某個(gè)表有n個(gè)列,則參數(shù)hbase.columns.mapping的值中就有n個(gè)以逗號(hào)分隔的條目。比如:

"hbase.columns.mapping" = ":key,a:b,a:c,d:e" 代表有兩個(gè)列族,一個(gè)是a一個(gè)是d,a列族中有兩列,分別為bc

注意,hbase.columns.mapping的值中是不允許出現(xiàn)空格的

 

2.每個(gè)匹配條目的形式必須是:key或者列族名:[列名][#(binary|string)](前面帶有#標(biāo)識(shí)的是在hive0.9才添加的,早期的版本把所有都當(dāng)作String類型)

       1)如果沒(méi)有給列或者列族指定類型,hbase.table.default.storage.type的值會(huì)被當(dāng)作這些列或者列族的類 

        2)表示類型的值(binary|string)的任何前綴都可以被用來(lái)表示這個(gè)類型,比如#b就代表了#binary

        3)如果指定列的類型為二進(jìn)制(binary)字節(jié),則在HBase的單元格的存儲(chǔ)類型也必須為二進(jìn)制字節(jié)

3.必須竄至一個(gè):key的形式匹配條目(不支持復(fù)合key的形式)

4.hive0.6版本以前,是通過(guò)第一個(gè)條目來(lái)作為關(guān)鍵字(key)字段,從0.6以后,都需要直接通過(guò):key的方式來(lái)指定

5.當(dāng)前沒(méi)有辦法可以訪問(wèn)到HBase的時(shí)間撮屬性,并且查詢總是訪問(wèn)到最新的數(shù)據(jù)(這條主要是因?yàn)?/span>hbase單元格數(shù)據(jù)存儲(chǔ)是有版本的,根據(jù)時(shí)間撮)

6. 因?yàn)?/span>HBase的列定義沒(méi)有包含有數(shù)據(jù)類型信息,所以在存儲(chǔ)的時(shí)候,會(huì)把所有的其它類型都轉(zhuǎn)換為string 代表;所以,列數(shù)據(jù)類型不支持自定義

7. 沒(méi)有必要對(duì)HBase的所有列族都進(jìn)行映射,但是沒(méi)有被映射的列族不能通過(guò)訪問(wèn)Hive表讀取到數(shù)據(jù);可以把多個(gè)Hive表映射到同一個(gè)HBase的表

 

下面的章節(jié)提供更加詳細(xì)的例子,來(lái)說(shuō)明當(dāng)前各種不同的列映射

多個(gè)列和列族

下面的例子包含三個(gè)Hive表的列以及兩個(gè)HBase表的列族,其中一個(gè)列族包括兩個(gè)列

CREATE TABLE hbase_table_1(key int, value1 string, value2 int, value3 int)

STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'

WITH SERDEPROPERTIES (

"hbase.columns.mapping" = ":key,a:b,a:c,d:e"

);

INSERT OVERWRITE TABLE hbase_table_1 SELECT foo, bar, foo+1, foo+2

FROM pokes WHERE foo=98 OR foo=100;

 

上面的例子中,hive擁有除去可以外的列為三個(gè),value1 value2 value3,對(duì)應(yīng)的HBase表為兩個(gè)列族,分別為ad,其中a包括兩列(bc);值的對(duì)應(yīng)關(guān)系從左到右一一對(duì)應(yīng),a列族中的b列對(duì)應(yīng)value1,c列對(duì)應(yīng)value2,d列族的e列對(duì)應(yīng)value3 

下面是從HBase中查看的結(jié)果:

hbase(main):014:0> describe "hbase_table_1"

DESCRIPTION                                                             ENABLED                              

 {NAME => 'hbase_table_1', FAMILIES => [{NAME => 'a', COMPRESSION => 'N true                                 

 ONE', VERSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN_M                                      

 EMORY => 'false', BLOCKCACHE => 'true'}, {NAME => 'd', COMPRESSION =>                                       

 'NONE', VERSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN                                      

 _MEMORY => 'false', BLOCKCACHE => 'true'}]}                                                                 

1 row(s) in 0.0170 seconds

hbase(main):015:0> scan "hbase_table_1"

ROW                          COLUMN+CELL                                                                     

 100                         column=a:b, timestamp=1267740457648, value=val_100                              

 100                         column=a:c, timestamp=1267740457648, value=101                                  

 100                         column=d:e, timestamp=1267740457648, value=102                                  

 98                          column=a:b, timestamp=1267740457648, value=val_98                               

 98                          column=a:c, timestamp=1267740457648, value=99                                   

 98                          column=d:e, timestamp=1267740457648, value=100                                  

2 row(s) in 0.0240 seconds

 

同一張表在Hive中的查詢結(jié)果是:

hive> select * from hbase_table_1;

Total MapReduce jobs = 1

Launching Job 1 out of 1

...

OK

100        val_100        101        102

98        val_98        99        100

Time taken: 4.054 seconds

 

Hive MAP(集合)Hbase 列族的映射

下面是HiveMAP數(shù)據(jù)類型與Hbase列族的映射例子。每行都可以包含不同的列組合,列名與map的可以對(duì)應(yīng),values與列值對(duì)應(yīng)。

CREATE TABLE hbase_table_1(value map<string,int>, row_key int)

STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'

WITH SERDEPROPERTIES (

"hbase.columns.mapping" = "cf:,:key"

);

INSERT OVERWRITE TABLE hbase_table_1 SELECT map(bar, foo), foo FROM pokes

WHERE foo=98 OR foo=100;

 

其中cf表示列族,冒號(hào)后面為空,它與Hive表的列value對(duì)應(yīng),即valuekeycf列族的列,可以通過(guò)下面HBase的查詢來(lái)理解key為列名,value為值的用法。

 

hbase(main):012:0> scan "hbase_table_1"

ROW                          COLUMN+CELL                                                                     

 100                         column=cf:val_100, timestamp=1267739509194, value=100                           

 98                          column=cf:val_98, timestamp=1267739509194, value=98                             

2 row(s) in 0.0080 seconds

 

cf為列族名,val_100hive表中MAP(集合)的key,100MAP(集合)中的val_100的值

 

下面是對(duì)應(yīng)的hive的查詢顯示結(jié)果:

hive> select * from hbase_table_1;

Total MapReduce jobs = 1

Launching Job 1 out of 1

...

OK

{"val_100":100}        100

{"val_98":98}        98

Time taken: 3.808 seconds

 

注意:MAP(集合)的key必須是string類型,否則會(huì)失敗,因?yàn)?/span>keyHBase列的名字;如下的定義將會(huì)失敗

CREATE TABLE hbase_table_1(key int, value map<int,int>)

STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'

WITH SERDEPROPERTIES (

"hbase.columns.mapping" = ":key,cf:"

);

FAILED: Error in metadata: java.lang.RuntimeException: MetaException(message:org.apache.hadoop.hive.serde2.SerDeException org.apache.hadoop.hive.hbase.HBaseSerDe: hbase column family 'cf:' should be mapped to map<string,?> but is mapped to map<int,int>)

 

注意:當(dāng)hbase.columns.mapping中有“:key,cf:”這樣的值,即列族冒號(hào)后面為空時(shí),表示Hive中對(duì)應(yīng)的類型為集合map,如果不是,則創(chuàng)建表會(huì)失敗

CREATE TABLE hbase_table_1(key int, value string)

STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'

WITH SERDEPROPERTIES (

"hbase.columns.mapping" = ":key,cf:"

);

FAILED: Error in metadata: java.lang.RuntimeException: MetaException(message:org.apache.hadoop.hive.serde2.SerDeException

org.apache.hadoop.hive.hbase.HBaseSerDe: hbase column family 'cf:' should be mapped to map<string,?> but is mapped to string)

 

hbase.columns.mapping中值類型用法列舉

如果沒(méi)有指定值的類型,比如cfval,則采用配置hbase.table.default.storage.type的值為數(shù)據(jù)類型

1.當(dāng)不配置hbase.table.default.storage.type時(shí),它默認(rèn)是string,如果有二進(jìn)制的數(shù)據(jù)類型,則如下定義:

CREATE TABLE hbase_table_1 (key int, value string, foobar double)

STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'

WITH SERDEPROPERTIES (

"hbase.columns.mapping" = ":key#b,cf:val,cf:foo#b"

);

2.如果顯示的指定hbase.table.default.storage.type為binary時(shí),如果類型有string類型,則需要指定,如:

CREATE TABLE hbase_table_1 (key int, value string, foobar double)

STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'

WITH SERDEPROPERTIES (

"hbase.columns.mapping" = ":key,cf:val#s,cf:foo",

"hbase.table.default.storage.type" = "binary"

);

 cf:val#s 中的#s就表示類型為string,cf:foo沒(méi)有配置類型,則采用hbase.table.default.storage.type的配置,為binary

 

添加時(shí)間戳

當(dāng)用hiveHBase的表添加記錄時(shí),時(shí)間戳默認(rèn)為當(dāng)前時(shí)間,如果想改變這個(gè)值,可以通過(guò)設(shè)置SERDEPROPERIES屬性的可選配置項(xiàng)hbase.put.timestamp,當(dāng)這個(gè)配置項(xiàng)為-1的時(shí)候,就是默認(rèn)策略,即添加記錄為當(dāng)前時(shí)間戳

CREATE TABLE hbase_table_1 (key int, value string, foobar double)

STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'

WITH SERDEPROPERTIES (

"hbase.columns.mapping" = ":key,cf:val#s,cf:foo",

"hbase.table.default.storage.type" = "binary"

"hbase.put.timestamp" = "2013-03-17 09:04:30"

)

 

主鍵唯一性

HBaseHive的表有一個(gè)細(xì)微的差別,就是HBase的表有一個(gè)主鍵,并且需要唯一,但是Hive沒(méi)有;如果不能保證這個(gè)主鍵的唯一,則HBase存儲(chǔ)的時(shí)候,只能存儲(chǔ)其中一個(gè),這會(huì)導(dǎo)致查詢的時(shí)候,hive總能找到正確的值,而HBase出來(lái)的結(jié)果就不確定

 

如下,在hive中查詢:

CREATE TABLE pokes2(foo INT, bar STRING);

INSERT OVERWRITE TABLE pokes2 SELECT * FROM pokes;

-- this will return 3

SELECT COUNT(1) FROM POKES WHERE foo=498;

-- this will also return 3

SELECT COUNT(1) FROM pokes2 WHERE foo=498;

 

同一張表在HBase中查詢,就會(huì)出來(lái)不確定的結(jié)果:

CREATE TABLE pokes3(foo INT, bar STRING)

STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'

WITH SERDEPROPERTIES (

"hbase.columns.mapping" = ":key,cf:bar"

);

INSERT OVERWRITE TABLE pokes3 SELECT * FROM pokes;

-- this will return 1 instead of 3

SELECT COUNT(1) FROM pokes3 WHERE foo=498;

 

 

覆蓋(Overwrite

當(dāng)執(zhí)行OVERWRITE時(shí),HBase中已經(jīng)存在的記錄是不會(huì)被刪除的;但是,如果存在的記錄與新紀(jì)錄的主鍵(key)是一樣的,則老數(shù)據(jù)會(huì)被覆蓋

 

 

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI