Hive體系結構

一、Hive架構與基本組成java

    下面是Hive的架構圖。python

圖1.1 Hive體系結構mysql

    Hive的體系結構能夠分爲如下幾部分:web

    (1)用戶接口主要有三個:CLI,Client 和 WUI。其中最經常使用的是CLI,Cli啓動的時候,會同時啓動一個Hive副本。Client是Hive的客戶端,用戶鏈接至Hive Server。在啓動 Client模式的時候,須要指出Hive Server所在節點,而且在該節點啓動Hive Server。 WUI是經過瀏覽器訪問Hive。
    (2)Hive將元數據存儲在數據庫中,如mysql、derby。Hive中的元數據包括表的名字,表的列和分區及其屬性,表的屬性(是否爲外部表等),表的數據所在目錄等。
    (3)解釋器、編譯器、優化器完成HQL查詢語句從詞法分析、語法分析、編譯、優化以及查詢計劃的生成。生成的查詢計劃存儲在HDFS中,並在隨後有MapReduce調用執行。
    (4)Hive的數據存儲在HDFS中,大部分的查詢、計算由MapReduce完成(包含*的查詢,好比select * from tbl不會生成MapRedcue任務)。正則表達式

    Hive將元數據存儲在RDBMS中,算法

 

有三種模式能夠鏈接到數據庫:sql

    (1) 單用戶模式。此模式鏈接到一個In-memory 的數據庫Derby,通常用於Unit Test。數據庫

圖2.1 單用戶模式apache

    (2)多用戶模式。經過網絡鏈接到一個數據庫中,是最常用到的模式。瀏覽器

 

 

圖2.2 多用戶模式

 

    (3) 遠程服務器模式。用於非Java客戶端訪問元數據庫,在服務器端啓動MetaStoreServer,客戶端利用Thrift協議經過MetaStoreServer訪問元數據庫。

 

    對於數據存儲,Hive沒有專門的數據存儲格式,也沒有爲數據創建索引,用戶能夠很是自由的組織Hive中的表,只須要在建立表的時候告訴Hive數據中 的列分隔符和行分隔符,Hive就能夠解析數據。Hive中全部的數據都存儲在HDFS中,存儲結構主要包括數據庫、文件、表和視圖。Hive中包含如下 數據模型:Table內部表,External Table外部表,Partition分區,Bucket桶。Hive默承認以直接加載文本文件,還支持sequence file 、RCFile。

 

    Hive的數據模型介紹以下:

    (1)Hive數據庫

    相似傳統數據庫的DataBase,在第三方數據庫裏實際是一張表。簡單示例命令行 hive > create database test_database;

 

    (2)內部表

    Hive的內部表與數據庫中的Table在概念上是相似。每個Table在Hive中都有一個相應的目錄存儲數據。例如一個表pvs,它在HDFS中的 路徑爲/wh/pvs,其中wh是在hive-site.xml中由${hive.metastore.warehouse.dir} 指定的數據倉庫的目錄,全部的Table數據(不包括External Table)都保存在這個目錄中。刪除表時,元數據與數據都會被刪除。

    內部表簡單示例:
    建立數據文件:test_inner_table.txt

    建立表:create table test_inner_table (key string)
    加載數據:LOAD DATA LOCAL INPATH ‘filepath’ INTO TABLE test_inner_table
    查看數據:select * from test_inner_table;  select count(*) from test_inner_table
    刪除表:drop table test_inner_table

 

    (3)外部表

    外部表指向已經在HDFS中存在的數據,能夠建立Partition。它和內部表在元數據的組織上是相同的,而實際數據的存儲則有較大的差別。內部表的建立過程和數據加載過程這兩個過程能夠分別獨立完成,也能夠在同一個語句中完成,在加載數據的過程當中,實際數據會被移動到數據倉庫目錄中;以後對數據對訪問將會直接在數據倉庫目錄中完成。刪除表時,表中的數據和元數據將會被同時刪除。而外部表只有一個過程,加載數據和建立表同時完成(CREATE EXTERNAL TABLE ……LOCATION),實際數據是存儲在LOCATION後面指定的 HDFS 路徑中,並不會移動到數據倉庫目錄中。當刪除一個External Table時,僅刪除該連接。
    外部表簡單示例:
    建立數據文件:test_external_table.txt
    建立表:create external table test_external_table (key string)
    加載數據:LOAD DATA INPATH ‘filepath’ INTO TABLE test_inner_table
    查看數據:select * from test_external_table;  •select count(*) from test_external_table
    刪除表:drop table test_external_table

 

    (4)分區

    Partition對應於數據庫中的Partition列的密集索引,可是Hive中Partition的組織方式和數據庫中的很不相同。在Hive中, 表中的一個Partition對應於表下的一個目錄,全部的Partition的數據都存儲在對應的目錄中。例如pvs表中包含ds和city兩個 Partition,則對應於ds = 20090801, ctry = US 的HDFS子目錄爲/wh/pvs/ds=20090801/ctry=US;對應於 ds = 20090801, ctry = CA 的HDFS子目錄爲/wh/pvs/ds=20090801/ctry=CA。

    分區表簡單示例:
    建立數據文件:test_partition_table.txt
    建立表:create table test_partition_table (key string) partitioned by (dt string)
    加載數據:LOAD DATA INPATH ‘filepath’ INTO TABLE test_partition_table partition (dt=‘2006’)
    查看數據:select * from test_partition_table;  select count(*) from test_partition_table
    刪除表:drop table test_partition_table

 

    (5)桶

    Buckets是將表的列經過Hash算法進一步分解成不一樣的文件存儲。它對指定列計算hash,根據hash值切分數據,目的是爲了並行,每個 Bucket對應一個文件。例如將user列分散至32個bucket,首先對user列的值計算hash,對應hash值爲0的HDFS目錄爲/wh /pvs/ds=20090801/ctry=US/part-00000;hash值爲20的HDFS目錄爲/wh/pvs/ds=20090801 /ctry=US/part-00020。若是想應用不少的Map任務這樣是不錯的選擇。

    桶的簡單示例:
    建立數據文件:test_bucket_table.txt
    建立表:create table test_bucket_table (key string) clustered by (key) into 20 buckets
    加載數據:LOAD DATA INPATH ‘filepath’ INTO TABLE test_bucket_table
    查看數據:select * from test_bucket_table;  set hive.enforce.bucketing = true;

 

    (6)Hive的視圖

    視圖與傳統數據庫的視圖相似。視圖是隻讀的,它基於的基本表,若是改變,數據增長不會影響視圖的呈現;若是刪除,會出現問題。•若是不指定視圖的列,會根據select語句後的生成。
    示例:create view test_view as select * from test

 

    二、Hive的執行原理


 

圖2.1 Hive的執行原理

    Hive構建在Hadoop之上, 
    (1)HQL中對查詢語句的解釋、優化、生成查詢計劃是由Hive完成的 
    (2)全部的數據都是存儲在Hadoop中 
    (3)查詢計劃被轉化爲MapReduce任務,在Hadoop中執行(有些查詢沒有MR任務,如:select * from table)
    (4)Hadoop和Hive都是用UTF-8編碼的

    Hive編譯器將一個Hive QL轉換操做符。操做符Operator是Hive的最小的處理單元,每一個操做符表明HDFS的一個操做或者一道MapReduce做業。Operator都是hive定義的一個處理過程,其定義有:
protected List <Operator<? extends Serializable >> childOperators; 
protected List <Operator<? extends Serializable >> parentOperators; 
protected boolean done;   // 初始化值爲false

    全部的操做構成了Operator圖,hive正是基於這些圖關係來處理諸如limit, group by, join等操做。

圖2.2 Hive QL的操做符

    操做符以下:
    TableScanOperator:掃描hive表數據
    ReduceSinkOperator:建立將發送到Reducer端的<Key,Value>對
    JoinOperator:Join兩份數據
    SelectOperator:選擇輸出列
    FileSinkOperator:創建結果數據,輸出至文件
    FilterOperator:過濾輸入數據
    GroupByOperator:GroupBy語句
    MapJoinOperator:/*+mapjoin(t) */
    LimitOperator:Limit語句
    UnionOperator:Union語句
    Hive經過ExecMapper和ExecReducer執行MapReduce任務。在執行MapReduce時有兩種模式,即本地模式和分佈式模式 。

    Hive編譯器的組成:

   



 

圖2.3 Hive編譯器的組成

    編譯流程以下:

 

   

圖2.4 Hive QL編譯流程



 

    三、Hive和數據庫的異同
    因爲Hive採用了SQL的查詢語言HQL,所以很容易將Hive理解爲數據庫。其實從結構上來看,Hive和數據庫除了擁有相似的查詢語言,再無相似之 處。數據庫能夠用在Online的應用中,可是Hive是爲數據倉庫而設計的,清楚這一點,有助於從應用角度理解Hive的特性。

    Hive和數據庫的比較以下表:

 

 

Hive

RDBMS

查詢語言

HQL

SQL

數據存儲

HDFS

Raw Device or Local FS

數據格式

用戶定義

系統決定

數據更新

不支持

支持

索引

執行

MapReduce

Executor

執行延遲

處理數據規模

可擴展性

 

     (1)查詢語言。因爲 SQL 被普遍的應用在數據倉庫中,所以專門針對Hive的特性設計了類SQL的查詢語言HQL。熟悉SQL開發的開發者能夠很方便的使用Hive進行開發。

 

     (2)數據存儲位置。Hive是創建在Hadoop之上的,全部Hive的數據都是存儲在HDFS中的。而數據庫則能夠將數據保存在塊設備或者本地文件系統中。

 

     (3)數據格式。Hive中沒有定義專門的數據格式,數據格式能夠由用戶指定,用戶定義數據格式須要指定三個屬性:列分隔符(一般爲空 格、」\t」、」\x001″)、行分隔符(」\n」)以及讀取文件數據的方法(Hive中默認有三個文件格式 TextFile,SequenceFile以及RCFile)。因爲在加載數據的過程當中,不須要從用戶數據格式到Hive定義的數據格式的轉換,所以,

Hive在加載的過程當中不會對數據自己進行任何修改,而只是將數據內容複製或者移動到相應的HDFS目錄中。

而在數據庫中,不一樣的數據庫有不一樣的存儲引擎,定義了本身的數據格式。全部數據都會按照必定的組織存儲,所以,數據庫加載數據的過程會比較耗時。

 

     (4)數據更新。因爲Hive是針對數據倉庫應用設計的,而數據倉庫的內容是讀多寫少的。所以,Hive中不支持對數據的改寫和添加,全部的數據都 是在加載的時候中肯定好的。而數據庫中的數據一般是須要常常進行修改的,所以可使用INSERT INTO ... VALUES添加數據,使用UPDATE ... SET修改數據。

 

     (5)索引。以前已經說過,Hive在加載數據的過程當中不會對數據進行任何處理,甚至不會對數據進行掃描,所以也沒有對數據中的某些Key創建索 引。Hive要訪問數據中知足條件的特定值時,須要暴力掃描整個數據,所以訪問延遲較高。因爲MapReduce的引入, Hive能夠並行訪問數據,所以即便沒有索引,對於大數據量的訪問,Hive仍然能夠體現出優點。數據庫中,一般會針對一個或者幾個列創建索引,所以對於 少許的特定條件的數據的訪問,數據庫能夠有很高的效率,較低的延遲。因爲數據的訪問延遲較高,決定了Hive不適合在線數據查詢。

 

     (6)執行。Hive中大多數查詢的執行是經過Hadoop提供的MapReduce來實現的(相似select * from tbl的查詢不須要MapReduce)。而數據庫一般有本身的執行引擎。

 

     (7)執行延遲。以前提到,Hive在查詢數據的時候,因爲沒有索引,須要掃描整個表,所以延遲較高。另一個致使Hive執行延遲高的因素是 MapReduce框架。因爲MapReduce自己具備較高的延遲,所以在利用MapReduce執行Hive查詢時,也會有較高的延遲。相對的,數據 庫的執行延遲較低。固然,這個低是有條件的,即數據規模較小,當數據規模大到超過數據庫的處理能力的時候,Hive的並行計算顯然能體現出優點。

 

     (8)可擴展性。因爲Hive是創建在Hadoop之上的,所以Hive的可擴展性是和Hadoop的可擴展性是一致的(世界上最大的Hadoop 集羣在Yahoo!,2009年的規模在4000臺節點左右)。而數據庫因爲ACID語義的嚴格限制,擴展行很是有限。目前最早進的並行數據庫 Oracle在理論上的擴展能力也只有100臺左右。

 

     (9)數據規模。因爲Hive創建在集羣上並能夠利用MapReduce進行並行計算,所以能夠支持很大規模的數據;對應的,數據庫能夠支持的數據規模較小。



四、Hive元數據庫

    Hive將元數據存儲在RDBMS 中,通常經常使用的有MYSQL和DERBY。

 

    啓動HIVE的元數據庫時,須要進入到hive的安裝目錄
    啓動derby數據庫:/home/admin/caona/hive/build/dist/,運行startNetworkServer -h 0.0.0.0。

    鏈接Derby數據庫進行測試:查看/home/admin/caona/hive/build/dist/conf/hive-default.xml。找到

  1.  
  2. <P style="TEXT-ALIGN: left; PADDING-BOTTOM: 0px; WIDOWS: 2; TEXT-TRANSFORM: none; BACKGROUND-COLOR: rgb(255,255,255); TEXT-INDENT: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; FONT: 14px/26px Arial; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px; PADDING-TOP: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"> </P>

複製代碼

進入derby安裝目錄:/home/admin/caona/hive/build/dist/db-derby-10.4.1.3-bin/bin
    輸入:./ij  Connect 'jdbc:derby://hadoop1:1527/metastore_db;create=true';

    hive元數據對應的表約有20個,其中和表結構信息有關的有9張,其他的10多張或爲空,或只有簡單的幾條記錄,如下是部分主要表的簡要說明。

表名 說明 關聯鍵
TBLS 全部hive表的基本信息 TBL_ID,SD_ID
TABLE_PARAM 表級屬性,如是否外部表,表註釋等 TBL_ID
COLUMNS Hive表字段信息(字段註釋,字段名,字段類型,字段序號) SD_ID
SDS 全部hive表、表分區所對應的hdfs數據目錄和數據格式 SD_ID,SERDE_ID
SERDE_PARAM 序列化反序列化信息,如行分隔符、列分隔符、NULL的表示字符等 SERDE_ID
PARTITIONS Hive表分區信息 PART_ID,SD_ID,TBL_ID
PARTITION_KEYS Hive分區表分區鍵 TBL_ID
PARTITION_KEY_VALS Hive表分區名(鍵值) PART_ID

    從上面表的內容來看,hive整個建立表的過程已經比較清楚了。
    (1)解析用戶提交hive語句,對其進行解析,分解爲表、字段、分區等hive對象 
    (2)根據解析到的信息構建對應的表、字段、分區等對象,從 SEQUENCE_TABLE中獲取構建對象的最新ID,與構建對象信息(名稱,類型等)一同經過DAO方法寫入到元數據表中去,成功後將SEQUENCE_TABLE中對應的最新ID+5。
    實際上咱們常見的RDBMS都是經過這種方法進行組織的,典型的如postgresql,其系統表中和hive元數據同樣裸露了這些id信息 (oid,cid等),而Oracle等商業化的系統則隱藏了這些具體的ID。經過這些元數據咱們能夠很容易的讀到數據諸如建立一個表的數據字典信息,比 如導出建表語名等。
 

    五、Hive基本操做

    Create Table語句的一些注意項:

    (1)CREATE TABLE建立一個指定名字的表。若是相同名字的表已經存在,則拋出異常;用戶能夠用IF NOT EXIST選項來忽略這個異常。
   (2)EXTERNAL 關鍵字可讓用戶建立一個外部表,在建表的同時指定一個指向實際數據的路徑( LOCATION ),Hive 建立內部表時,會將數據移動到數據倉庫指向的路徑;若建立外部表,僅記錄數據所在的路徑,不對數據的位置作任何改變。在刪除表的時候,內部表的元數據和數 據會被一塊兒刪除,而外部表只刪除元數據,不刪除數據。
    (3)LIKE容許用戶複製現有的表結構,可是不復制數據。
    (4)用戶在建表的時候能夠自定義SerDe或者使用自帶的 SerDe ( Serialize/Deserilize 的簡稱,目的是用於序列化和反序列化 )。若是沒有指定 ROW FORMAT 或者 ROW FORMAT DELIMITED,將會使用自帶的SerDe。在建表的時候,用戶還須要爲表指定列,用戶在指定表的列的同時也會指定自定義的SerDe,Hive經過 SerDe肯定表的具體的列的數據。
    (5)若是文件數據是純文本,可使用STORED AS TEXTFILE。若是數據須要壓縮,使用STORED AS SEQUENCE。
    (6)有分區的表能夠在建立的時候使用 PARTITIONED B Y語句。一個表能夠擁有一個或者多個分區,每個分區單獨存在一個目錄下。並且,表和分區均可以對某個列進行CLUSTERED BY操做,將若干個列放入一個桶(bucket)中。也能夠利用SORT BY對數據進行排序。這樣能夠爲特定應用提升性能。
    (7)表名和列名不區分大小寫,SerDe和屬性名區分大小寫。表和列的註釋是字符串。

    Alter Table語句:主要功能包括Add Partitions, Drop Partitions, Rename Table, Change Column, Add/Replace Columns。

    Create View語句:建立視圖。格式CREATE VIEW [IF NOT EXISTS] view_name [ (column_name [COMMENT column_comment], ...) ]

    Showy語句:Show tables;  Show partitions; describe查看錶結構。

    Load語句:HIVE裝載數據時沒有作任何轉換,加載到表中的數據只是進入相應的配置單元表的位置。Load操做只是單純的複製/移動操做,將數據文件移動到Hive表對應的位置。

    Insert語句:插入數據。Hive不支持一條一條的用 insert 語句進行插入操做,這個應該是與hive的storage layer是有關係的,由於它的存儲層是HDFS,插入一個數據要全表掃描,還不如用整個表的替換來的快些。Hive也不支持update的操做。數據是 以load的方式,加載到創建好的表中。數據一旦導入,則不可修改。要麼drop掉整個表,要麼創建新的表,導入新的數據。

    Drop語句:刪除一個內部表的同時會同時刪除表的元數據和數據。刪除一個外部表,只刪除元數據而保留數據。

    Limit子句:能夠限制查詢的記錄數。查詢的結果是隨機選擇的。下面的查詢語句從 t1 表中隨機查詢5條記錄,SELECT * FROM t1 LIMIT 5。

    Top K查詢:下面的查詢語句查詢銷售記錄最大的 5 個銷售表明。
SET mapred.reduce.tasks = 1
SELECT * FROM sales SORT BY amount DESC LIMIT 5

    正則表達式使用:SELECT語句可使用正則表達式作列選擇,下面的語句查詢除了ds和h 以外的全部列:
SELECT `(ds|hr)?+.+` FROM sales

    SELECT語句:查詢數據。

    Group by, Order by, Sort by子句:聚合可進一步分爲多個表,甚至發送到 Hadoop 的 DFS 的文件(能夠進行操做,而後使用HDFS的utilitites)。能夠用hive.map.aggr控制怎麼進行彙總。默認爲爲true,配置單元會作 的第一級聚合直接在MAP上的任務。這一般提供更好的效率,但可能須要更多的內存來運行成功。

    Join語句:鏈接操做。一些注意事項:

    (1)Hive只支持等值鏈接(equality joins)、外鏈接(outer joins)和(left/right joins)。Hive不支持全部非等值的鏈接,由於非等值鏈接很是難轉化到map/reduce任務。

    (2)Hive 支持多於2個表的鏈接。

    (3)join 時,每次 map/reduce 任務的邏輯: reducer 會緩存 join 序列中除了最後一個表的全部表的記錄, 再經過最後一個表將結果序列化到文件系統。這一實現有助於在reduce端減小內存的使用量。實踐中,應該把最大的那個表寫在最後(不然會由於緩存浪費大 量內存)。

    (4)LEFT,RIGHT 和 FULL OUTER 關鍵字用於處理 join 中空記錄的狀況。

    (5)LEFT SEMI JOIN 是 IN/EXISTS 子查詢的一種更高效的實現。Hive 當前沒有實現 IN/EXISTS 子查詢,因此你能夠用 LEFT SEMI JOIN 重寫你的子查詢語句。LEFT SEMI JOIN的限制是, JOIN子句中右邊的表只能在ON子句中設置過濾條件,在WHERE子句、SELECT子句或其餘地方過濾都不行。

    六、使用HIVE注意點
    (1)字符集
    Hadoop和Hive都是用UTF-8編碼的,因此, 全部中文必須是UTF-8編碼, 才能正常使用。
    備註:中文數據load到表裏面,,若是字符集不一樣,頗有可能全是亂碼須要作轉碼的,可是hive自己沒有函數來作這個。
    (2)壓縮
    hive.exec.compress.output 這個參數,默認是false,可是不少時候貌似要單獨顯式設置一遍,不然會對結果作壓縮的,若是你的這個文件後面還要在hadoop下直接操做,那麼就不能壓縮了。
    (3)count(distinct)
    當前的Hive不支持在一條查詢語句中有多Distinct。若是要在Hive查詢語句中實現多Distinct,須要使用至少n+1條查詢語句(n爲 distinct的數目),前n條查詢分別對n個列去重,最後一條查詢語句對n個去重以後的列作Join操做,獲得最終結果。
    (4)JOIN
    只支持等值鏈接
    (5)DML操做
    只支持INSERT/LOAD操做,無UPDATE和DELTE
    (6)HAVING
    不支持HAVING操做。若是須要這個功能要嵌套一個子查詢用where限制
    (7)子查詢
    Hive不支持where子句中的子查詢
    (8)Join中處理null值的語義區別
    SQL標準中,任何對null的操做(數值比較,字符串操做等)結果都爲null。Hive對null值處理的邏輯和標準基本一致,除了Join時的特殊 邏輯。這裏的特殊邏輯指的是,Hive的Join中,做爲Join key的字段比較,null=null是有意義的,且返回值爲true。

    (9)分號字符

    分號是SQL語句結束標記,在HiveQL中也是,可是在HiveQL中,對分號的識別沒有那麼智慧,例如:
select concat(cookie_id,concat(';',’zoo’)) from c02_clickstat_fatdt1 limit 2;
FAILED: Parse Error: line 0:-1 cannot recognize input '<EOF>' in function specification
    能夠推斷,Hive解析語句的時候,只要遇到分號就認爲語句結束,而不管是否用引號包含起來。
    解決的辦法是,使用分號的八進制的ASCII碼進行轉義,那麼上述語句應寫成: 
select concat(cookie_id,concat('\073','zoo')) from c02_clickstat_fatdt1 limit 2;
    爲何是八進制ASCII碼?我嘗試用十六進制的ASCII碼,但Hive會將其視爲字符串處理並未轉義,好像僅支持八進制,緣由不詳。這個規則也適用於 其餘非SELECT語句,如CREATE TABLE中須要定義分隔符,那麼對不可見字符作分隔符就須要用八進制的ASCII碼來轉義。

    (10)Insert

    根據語法Insert必須加「OVERWRITE」關鍵字,也就是說每一次插入都是一次重寫。

    七、Hive的擴展特性

    Hive 是一個很開放的系統,不少內容都支持用戶定製,包括:
    * 文件格式:Text File,Sequence File
    * 內存中的數據格式: Java Integer/String, Hadoop IntWritable/Text
    * 用戶提供的map/reduce腳本:無論什麼語言,利用stdin/stdout傳輸數據
    * 用戶自定義函數:Substr, Trim, 1 – 1
    * 用戶自定義聚合函數:Sum, Average…… n – 1

   (1)數據文件格式

  TextFile SequenceFIle RCFFile
Data type Text Only Text/Binary Text/Binary
Internal Storage Order Row-based Row-based Column-based
Compression File Based Block Based Block Based
Splitable YES YES YES
Splitable After Compression No YES YES

     例如使用文件文件格式存儲建立的表:

  1. CREATE TABLE mylog ( user_id BIGINT, page_url STRING, unix_time INT)
  2. STORED AS TEXTFILE;

複製代碼

  當用戶的數據文件格式不能被當前Hive所識別的時候,能夠自定義文件格式。能夠參考contrib/src/java/org/apache /hadoop/hive/contrib/fileformat/base64中的例子。寫完自定義的格式後,在建立表的時候指定相應的文件格式就可 以:

 

  1. CREATE TABLE base64_test(col1 STRING, col2 STRING)
  2. STORED AS
  3. INPUTFORMAT 'org.apache.hadoop.hive.contrib.
  4. fileformat.base64.Base64TextInputFormat'
  5. OUTPUTFORMAT 'org.apache.hadoop.hive.contrib.
  6. fileformat.base64.Base64TextOutputFormat';

複製代碼

(2)SerDe
    SerDe是Serialize/Deserilize的簡稱,目的是用於序列化和反序列化。序列化的格式包括:分隔符(tab、逗號、CTRL-A)、Thrift 協議
    反序列化(內存內):Java Integer/String/ArrayList/HashMap、Hadoop Writable類、用戶自定義類
   其中,LazyObject只有在訪問到列的時候才進行反序列化。 BinarySortable保留了排序的二進制格式。
    當存在如下狀況時,能夠考慮增長新的SerDe:
    * 用戶的數據有特殊的序列化格式,當前的Hive不支持,而用戶又不想在將數據加載至Hive前轉換數據格式。
    * 用戶有更有效的序列化磁盤數據的方法。
    用戶若是想爲Text數據增長自定義Serde,能夠參照contrib/src/java/org/apache/hadoop/hive /contrib/serde2/RegexSerDe.java中的例子。RegexSerDe利用用戶提供的正則表卻是來反序列化數據,例如:

 

  1. CREATE TABLE apache_log(
  2. host STRING,
  3. identity STRING,
  4. user STRING,
  5. time STRING,
  6. request STRING,
  7. status STRING,
  8. size STRING,
  9. referer STRING,
  10. agent STRING)
  11. ROW FORMAT
  12. SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
  13. WITH SERDEPROPERTIES
  14. ( "input.regex" = "([^ ]*) ([^ ]*) ([^ ]*) (-|\\[[^\\]]*\\])
  15. ([^ \"]*|\"[^\"]*\") (-|[0-9]*) (-|[0-9]*)(?: ([^ \"]*|\"[^\"]*\")
  16. ([^ \"]*|\"[^\"]*\"))?",
  17. "output.format.string" = "%1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s";)
  18. STORED AS TEXTFILE;

複製代碼

    用戶若是想爲Binary數據增長自定義的SerDe,能夠參考例子serde/src/java/org/apache/hadoop/hive/serde2/binarysortable,例如:

 

  1. CREATE TABLE mythrift_table
  2. ROW FORMAT SERDE
  3. 'org.apache.hadoop.hive.contrib.serde2.thrift.ThriftSerDe'
  4. WITH SERDEPROPERTIES (
  5. "serialization.class" = "com.facebook.serde.tprofiles.full",
  6. "serialization.format" = "com.facebook.thrift.protocol.TBinaryProtocol";);

複製代碼


(3)Map/Reduce腳本(Transform)
    用戶能夠自定義Hive使用的Map/Reduce腳本,好比:

 

  1. FROM (
  2. SELECT TRANSFORM(user_id, page_url, unix_time)
  3. USING 'page_url_to_id.py'
  4. AS (user_id, page_id, unix_time)
  5. FROM mylog
  6. DISTRIBUTE BY user_id
  7. SORT BY user_id, unix_time)
  8. mylog2
  9. SELECT TRANSFORM(user_id, page_id, unix_time)
  10. USING 'my_python_session_cutter.py' AS (user_id, session_info);

複製代碼


    Map/Reduce腳本經過stdin/stdout進行數據的讀寫,調試信息輸出到stderr。
    (4)UDF(User-Defined-Function)
    用戶能夠自定義函數對數據進行處理,例如:

 

  1.  
  2. <P>[sql]</P>
  3. <P>add jar build/ql/test/test-udfs.jar;
  4. CREATE TEMPORARY FUNCTION testlength
  5. AS 'org.apache.hadoop.hive.ql.udf.UDFTestLength'; 
  6.  
  7. SELECT testlength(src.value) FROM src; 
  8.  
  9. DROP TEMPORARY FUNCTION testlength;</P>

複製代碼


UDFTestLength.java爲:

 

  1. package org.apache.hadoop.hive.ql.udf; 
  2.  
  3. public class UDFTestLength extends UDF {
  4. public Integer evaluate(String s) {
  5. if (s == null) {
  6. return null;
  7. }
  8. return s.length();
  9. }
  10. }

複製代碼


UDF 具備如下特性:
    * 用java寫UDF很容易。
    * Hadoop的Writables/Text 具備較高性能。
    * UDF能夠被重載。
    * Hive支持隱式類型轉換。
    * UDF支持變長的參數。
    * genericUDF 提供了較好的性能(避免了反射)。

 

    (5)UDAF(User-Defined Aggregation Funcation)
    例子:

  1.  
  2. <P>[sql]</P>
  3. <P>SELECT page_url, count(1), count(DISTINCT user_id) FROM mylog;</P>

複製代碼

UDAFCount.java代碼以下:

 

  1. public class UDAFCount extends UDAF {
  2. public static class Evaluator implements UDAFEvaluator {
  3. private int mCount; 
  4.  
  5. public void init() {
  6. mcount = 0;
  7.  
  8. public boolean iterate(Object o) {
  9. if (o!=null)
  10. mCount++; 
  11.  
  12. return true;
  13.  
  14. public Integer terminatePartial() {
  15. return mCount;
  16.  
  17. public boolean merge(Integer o) {
  18. mCount += o;
  19. return true;
  20.  
  21. public Integer terminate() {
  22. return mCount;
  23. }
  24. }

複製代碼

相關文章
相關標籤/搜索