1. 程式人生 > >hive 總體架構解析

hive 總體架構解析

最近整理了下自己以前的筆記,對Hive整體執行流程做了一些總結。

一、Hive簡介和原理

       1)Hive起源

         Hive起源於FACEBOOK,由FACEBOOK的幾名員工共同提出。最早提出的Hive概念來源於以下論文Hive——A Warehousing Solution Over A Map-Reduce Framework(論文見目錄)。它是基於MapReduce框架的資料倉庫的解決方案。主要解決了並行執行資料分析和機器查詢的效率。Hive已經成為最流行的基於Hadoop的資料儲存框架和資料分析框架,以及事實的大資料SQL標準和元資料標準;是Hadoop生態棧中最主要的基礎架構。

         Hive主要是面向非專業人士,尤其是大資料分析師最好的工具。Hive的提供的功能非常健全,是效率最高、便於使用的作業提交工具。

簡化後的HIVE架構:


     2)HIVE工作流


         HIVE的最小處理單元是OPERATORS ,OPERATORS(該術語來源於關係型資料中的術語,操作符。)可以是執行在叢集的MAP任務,也可以是執行在叢集的REDUCE任務,或者是執行在本地對於HDFS的操作;這些都會被抽象成OPERATORS。

         HIVE的COMPILER的作用是:把一條HIVE SQL,轉換為一個OPERATORS的 圖(這裡大部分情況下會是一個樹,樹狀結構)。

         HIVE中OPERATORS的種類:

OPERATORS

FUNCTION DESCRIBLE

縮寫

TableScanOperator         

從表中讀取資料                  

TS                     

ReduceSinkOperator       

把資料傳送給Reduce端作聚合操作    

RS                     

JoinOperator                      

作兩個表的關聯操作Join            

JOIN                    

SelectOperator(投影)       

選擇部分列並輸出                    

SEL                  

FileSinkOperator      

建立結果資料併發送給檔案         

FS                               

FilterOperator

過濾輸入資料

FIL

GroupByOperator

對資料作Group By操作

GBY

MapJoinOperator

在記憶體中作大表和小表的關聯操作

MapJOIN

LimitOperator

作limit,返回一定條目的資料

LIMIT

UnionOperator

作union

UNION


在較老的版本中,HIVE通常是一個MAPREDUCE作業(新版本可能是TEZ)。MAPPER是EXECMAPPER,REDUCER是EXECREDUCE。DRICVER實際上有多種處理模式,例如本地模式和分散式模式。

         在HIVE中最核心的模組就是COMPILER,它負責將一個字串(HIVESQL),轉化成一個執行計劃。


簡化後的執行流程圖:


為了說明上述執行流程,需要輔助一個簡單的Hive查詢例子:

案例1-1:Hive執行以下語句:
INSERT OVERWRITE TABLE access_log_temp2
SELECT a.user, a.prono, a.maker, a.price FROM access_log_hbase a JOIN product_hbase p 
ON (a.prono = p.prono)

3)具體執行流程:

(1)Parser生成AST


HQL生成的語法解析樹(AST):
HIVE主要是利用UNDERLER處理得到上面的抽象語法樹(這棵抽象語法樹主要是根據underller的分詞規則來確定根結點和左右孩子的,Hive的這部分處理是利用underller進行的)。
(2)Semantic Analyzer生成Query Block(QB)


Tip:                                                                                                          
第二步會將抽象語法樹按照QB的方式轉換為由QB組成的樹。通常情況下,每一個From子句會生成一個QB(Query Block)。通過檢視具體有多少個QB就可檢視Hive sql語句最終優化成多少個MapReduce的作業。

QB是由兩個子資料結構組成即MetaData(元資料資訊)和ParseInfo。語義分析的主要過程是向QB中填充元資料,另一個過程則是摘取AST的子節點,儲存在ParseInfo中。Semantic Analyzer過程主要是經過以上兩個過程,然後把QB關聯起來形成一個由QB構成的圖.

Logical Plan generator會將上一步生成的Query Block按照前文講的幾種的Operator,轉換為Operator Tree。



由於Hive查詢語句會將最後的查詢結果寫入到表access_log_temp2中,所以QB的MetaData中的Name To Destination…會轉化為Operator Tree中的FileSinkOperator(檔案下沉)。
最後會生成如下的OP Tree:

Logical Plan Generator (Result)

這裡就得到了一個有向無環圖(DAG),當在傳統資料庫中會對上圖進行優化然後執行;而在Hadoop叢集中這張圖是不行的,因為在叢集中執行需要對這張圖進行優化、切片,分散式化轉化為MapReduce作業然後執行。

(4)LOGICAL OPTIMIZER

         首先,Hive會對上圖進行優化,重繪。

         這裡需要介紹Hive中的優化器如下表:

優化器                    

簡介                    

LineageGenerator                      

各個Operator血緣情況的設定,優化Operator的血緣關係           

 ColumnPruner        

列剪裁優化器                            

Predicate PushDown  

謂詞下推優化器,將條件推到特定位置(where條件)            

PartitionPruner    

分割槽裁剪條件優化器                         

PartitionCondition Remove               

PartitionPruner消除無用的分支的優化器                     

GroupByOptimizer  

Group by優化兩階段中的Map端預階段聚合的優化器                  

SamplePruner    

抽樣優化器,降低抽樣的資料量                      

MapJoinProcessor   

在特定的情況下,把JoinOperator改寫成MapJoinOperator的          

優化器                                     

BucketMapJoin Optimizer               

對Bucket表做MapJoin的優化器                       

SortedMergeBucket MapJoinOptimizer               

對SortedMergeBucket進行MapJoin的優化器                

優化器                    

簡介                               

UnionProcessor     

識別兩邊的子查詢是否都是Map-Only的                 

JoinReader            

/*+ STREAMTABLE(A) */ 指定Join的               

ReduceSink                  

DeDuplication         

如果兩個ReduceSink的操作符共享分割槽和排列順序也一樣,此時就可以將這兩個表放在一起進行ReduceSink操作,提高效率。

上表中的優化器都是邏輯優化器。為了進一步介紹這些優化器,這裡舉個例子來進行說明。

         案例1-2 LOGICALOPTIMIZER(PREDIC PUSHDOWN)

         INSERTOVERWRITE TABLE access_log_temp2

         SELECTa.user, a.prono, a.maker, a.price FROM access_log_hbase a JOIN product_hbase p

                   ON(a.prono = p.prono) where p.mark = “honda”;

         此時,原來的邏輯計劃圖就會增加一個節點,如下圖:


這是一個未進行優化的OP Tree,此時會存在一個問題:當access_log_hbase和product_hbase兩個表的資料量非常大的時候,第三步進行的Join操作,就會產生海量的數之前就先進性過濾出”honda”的資料,此時向Reduce端傳送的資料會變得很少,Join時資料也會變得很少,從而大幅度提高Hive SQL的執行效率。這一個優化的過程就叫做謂詞下推,即把where選擇過濾操作下推到合適的步驟進行。
進過謂詞下推優化器優化後的OP Tree如下圖:


(5)PHYSICAL PLAN GENERATOR 


物理執行計劃會將OP Tree切成若干個Task,而一個Task就對應著一個MapReduce作業。由於案例中只有一個QB,所以最後會生成一個Task即一個MapReduce作業。
當DAG中存在Join或者Group By時,會在這個Operator之前的節點操作會在Map中執行,而這個Operator之後的節點都會在Reduce執行。而兩者會通過ReduceSinkOperator操作來連線,這個操作符會將Map端的資料傳送到Reduce端。


PHYSICAL PLAN GENERATOR (Result)


這樣就將一個OP Tree轉換為了一個Map-Red的作業。但是這個Map-Red作業還需要進行物理級別的優化。


(6)PHYSICAL OPTIMIZER
物理優化器


物理優化的類主要在Hive的org/apache/hadoop/hive/ql/optimizer/physical/包內。
主要有以下幾個物理優化器。



i)以MapJoinResolver為例,介紹物理優化
請看下圖(前例優化後的物理執行計劃)

1.此時,只有Map過程,即在本地進行小表的壓縮、上傳;在服務端讀大表然後進行關聯。
2.在進行Join時,一般使用者都會使用MapJoin來手動指令Select Map Join來進行操作。但是,如果用在進行Join時,使用者並不知道哪個表大哪個表小也不知道該不該使用Map Join,此時使用CommonJoinResolver則會解決這一問題。首先不管表大還是表小,他都會對Task Tree做一定的優化,會在Join 的Map-Red Task之前加上一個conditional Task。當作業到執行到Conditional Task時,會在執行Join的Map-Red作業之前對錶的大小先進行判斷;如果表是大表則進行Join操作;當表是小表時則進行MapJoin操作。這樣使用者就不必關心表大還是小,也不需要關心具體執行過程。
這裡把原來的物理計劃中Join換成了MapJoin,從而避免了Map-Red過程,轉換成為了只有Map過程的Task。從而避免了資料在各個節點之間的傳輸,大幅度提高了Task的執行效率。但是,這個物理執行計劃的DAG是不能直接執行的,這裡無法確定那個是大表,從而無法確定那個表要讀入到記憶體。而物理優化器的作用就是對一個Task Tree(DAG)進行優化,選出讀入記憶體的表,進行合理的優化提高執行效率。
具體轉換過程見下圖:

轉換後Task Tree是由兩個Task組成的DAG。第一個Task是在本地進行MapredLocalTask,首先會在本地讀小表,然後把小表通過HashTableSinkOperator轉換為一個Hashtable,然後打包、壓縮,通過DistrubuteChach機制將其上傳到伺服器上。
在伺服器上會先去讀取大表,然後MapJoinOperator會去下載小表,然後將其讀入到記憶體中,然後再記憶體中進行MapJoin。由於Map Join是在記憶體中進行的,並且此時只是均勻的去讀一個大表,每個程序只讀64M,可以在一個均勻的時間內完成Select並輸出。此時只需要客戶端都一個小表,伺服器都一個大表完成MapJoin操作。
物理優化器的作用主要是改寫Task Tree,根據不同的情況有不同的給些方式。詳細內容請檢視物理優化部分。

最後,來整體做個總結。
Hive 整體架構:



執行流程回顧:

補充:如何檢視執行計劃?
 只需要在Hive中執行的SQL語句前面加上EXPLAN語句。

**tip**

這裡的總結都是我參加hive2.1培訓的筆記(小象學院)。

雖然大體上對整個hive的執行流程做了個總結吧。但是對於初學者還是很難全部理解的,後面我會整理一些更細節的hive各個模組的具體理解內容。