Hive SQL 編譯過程

來源:互聯網
上載者:User

標籤:

轉自:http://www.open-open.com/lib/view/open1400644430159.html

Hive跟Impala貌似都是公司或者研究所常用的系統,前者更穩定點,實現方式是MapReduce,因為用Hue的時候,在groupby中文的時候,出現了點問題,並且看到寫很長的SQL語句,經常會看到起很多個Job,因此想瞭解下Hive怎麼將SQL轉化成MapReduce的Job。以後寫SQL的時候,大概就瞭解怎麼去做最佳化了。下面是看到的一片優秀的文章(美團的技術部落格),我粘過來mark下:

 

Hive是基於Hadoop的一個資料倉儲系統,在各大公司都有廣泛的應用。美團資料倉儲也是基於Hive搭建,每天執行近萬次的Hive ETL計算流程,負責每天數百GB的資料存放區和分析。Hive的穩定性和效能對我們的資料分析非常關鍵。

在 幾次升級Hive的過程中,我們遇到了一些大大小小的問題。通過向社區的諮詢和自己的努力,在解決這些問題的同時我們對Hive將SQL編譯為 MapReduce的過程有了比較深入的理解。對這一過程的理解不僅協助我們解決了一些Hive的bug,也有利於我們最佳化Hive SQL,提升我們對Hive的掌控力,同時有能力去定製一些需要的功能。

1、MapReduce實現基本SQL操作的原理

詳細講解SQL編譯為MapReduce之前,我們先來看看MapReduce架構實現SQL基本操作的原理

1.1 Join的實現原理
select u.name, o.orderid from order o join user u on o.uid = u.uid;

在map的輸出value中為不同表的資料打上tag標記,在reduce階段根據tag判斷資料來源。MapReduce的過程如下(這裡只是說明最基本的Join的實現,還有其他的實現方式)

1.2 Group By的實現原理
select rank, isonline, count(*) from city group by rank, isonline;

將GroupBy的欄位組合為map的輸出key值,利用MapReduce的排序,在reduce階段儲存LastKey區分不同的key。MapReduce的過程如下(當然這裡只是說明Reduce端的非Hash彙總過程)

1.3 Distinct的實現原理
select dealid, count(distinct uid) num from order group by dealid;

當 只有一個distinct欄位時,如果不考慮Map階段的Hash GroupBy,只需要將GroupBy欄位和Distinct欄位組合為map輸出key,利用mapreduce的排序,同時將GroupBy欄位作 為reduce的key,在reduce階段儲存LastKey即可完成去重

如果有多個distinct欄位呢,如下面的SQL

select dealid, count(distinct uid), count(distinct date) from order group by dealid;

實現方式有兩種:

(1)如果仍然按照上面一個distinct欄位的方法,即這種實現方式,無法跟據uid和date分別排序,也就無法通過LastKey去重,仍然需要在reduce階段在記憶體中通過Hash去重

(2)第二種實現方式,可以對所有的distinct欄位編號,每行資料產生n行資料,那麼相同欄位就會分別排序,這時只需要在reduce階段記錄LastKey即可去重。

這種實現方式很好的利用了MapReduce的排序,節省了reduce階段去重的記憶體消耗,但是缺點是增加了shuffle的資料量。

需要注意的是,在產生reduce value時,除第一個distinct欄位所在行需要保留value值,其餘distinct資料行value欄位均可為空白。

2、SQL轉化為MapReduce的過程

瞭解了MapReduce實現SQL基本操作之後,我們來看看Hive是如何將SQL轉化為MapReduce任務的,整個編譯過程分為六個階段:

  1. Antlr定義SQL的文法規則,完成SQL詞法,文法解析,將SQL轉化為抽象文法樹AST Tree
  2. 遍曆AST Tree,抽象出查詢的基本組成單元QueryBlock
  3. 遍曆QueryBlock,翻譯為執行操作樹OperatorTree
  4. 邏輯層最佳化器進行OperatorTree變換,合并不必要的ReduceSinkOperator,減少shuffle資料量
  5. 遍曆OperatorTree,翻譯為MapReduce任務
  6. 物理層最佳化器進行MapReduce任務的變換,產生最終的執行計畫

下面分別對這六個階段進行介紹

2.1 Phase1 SQL詞法,文法解析2.1.1 Antlr

Hive使用Antlr實現SQL的詞法和文法解析。Antlr是一種語言識別的工具,可以用來構造領域語言。
這裡不詳細介紹Antlr,只需要瞭解使用Antlr構造特定的語言只需要編寫一個文法檔案,定義詞法和文法替換規則即可,Antlr完成了詞法分析、文法分析、語義分析、中間代碼產生的過程。

Hive 中文法規則的定義檔案在0.10版本以前是Hive.g一個檔案,隨著文法規則越來越複雜,由文法規則產生的Java解析類可能超過Java類檔案的最大 上限,0.11版本將Hive.g拆成了5個檔案,詞法規則HiveLexer.g和文法規則的4個檔案 SelectClauseParser.g,FromClauseParser.g,IdentifiersParser.g,HiveParser.g。

2.1.2 抽象文法樹AST Tree

經過詞法和文法解析後,如果需要對錶達式做進一步的處理,使用 Antlr 的抽象文法樹文法Abstract Syntax Tree,在文法分析的同時將輸入語句轉換成抽象文法樹,後續在遍曆文法樹時完成進一步的處理。

下面的一段文法是Hive SQL中SelectStatement的文法規則,從中可以看出,SelectStatement包含select, from, where, groupby, having, orderby等子句。
(在下面的文法規則中,箭頭表示對於原語句的改寫,改寫後會加入一些特殊詞標示特定文法,比如TOK_QUERY標示一個查詢塊)

selectStatement   :   selectClause   fromClause   whereClause?   groupByClause?   havingClause?   orderByClause?   clusterByClause?   distributeByClause?   sortByClause?   limitClause? -> ^(TOK_QUERY fromClause ^(TOK_INSERT ^(TOK_DESTINATION ^(TOK_DIR TOK_TMP_FILE))                     selectClause whereClause? groupByClause? havingClause? orderByClause? clusterByClause?                     distributeByClause? sortByClause? limitClause?))   ;
2.1.3 範例SQL

為了詳細說明SQL翻譯為MapReduce的過程,這裡以一條簡單的SQL為例,SQL中包含一個子查詢,最終將資料寫入到一張表中

FROM(   SELECT    p.datekey datekey,    p.userid userid,    c.clienttype  FROM    detail.usersequence_client c    JOIN fact.orderpayment p ON p.orderid = c.orderid    JOIN default.user du ON du.userid = p.userid  WHERE p.datekey = 20131118 ) baseINSERT OVERWRITE TABLE `test`.`customer_kpi`SELECT  base.datekey,  base.clienttype,  count(distinct base.userid) buyer_countGROUP BY base.datekey, base.clienttype
2.1.3 SQL產生AST Tree

Antlr對Hive SQL解析的代碼如下,HiveLexerX,HiveParser分別是Antlr對文法檔案Hive.g編譯後自動產生的詞法解析和文法解析類,在這兩個類中進行複雜的解析。

HiveLexerX lexer = new HiveLexerX(new ANTLRNoCaseStringStream(command));    //詞法解析,忽略關鍵詞的大小寫TokenRewriteStream tokens = new TokenRewriteStream(lexer);if (ctx != null) {  ctx.setTokenRewriteStream(tokens);}HiveParser parser = new HiveParser(tokens);                                 //文法解析parser.setTreeAdaptor(adaptor);HiveParser.statement_return r = null;try {  r = parser.statement();                                                   //轉化為AST Tree} catch (RecognitionException e) {  e.printStackTrace();  throw new ParseException(parser.errors);}

最終產生的AST Tree如右側(使用Antlr Works產生,Antlr Works是Antlr提供的編寫文法檔案的編輯器),圖中只是展開了骨架的幾個節點,沒有完全展開。
子查詢1/2,分別對應右側第1/2兩個部分。

這 裡注意一下內層子查詢也會產生一個TOK_DESTINATION節點。請看上面SelectStatement的文法規則,這個節點是在文法改寫中特意 增加了的一個節點。原因是Hive中所有查詢的資料均會儲存在HDFS臨時的檔案中,無論是中間的子查詢還是查詢最終的結果,Insert語句最終會將數 據寫入表所在的HDFS目錄下。

詳細來看,將記憶體子查詢的from子句展開後,得到如下AST Tree,每個表產生一個TOK_TABREF節點,Join條件產生一個“=”節點。其他SQL部分類似,不一一詳述。

2.2 Phase2 SQL基本組成單元QueryBlock

AST Tree仍然非常複雜,不夠結構化,不方便直接翻譯為MapReduce程式,AST Tree轉化為QueryBlock就是將SQL進一部抽象和結構化。

2.2.1 QueryBlock

QueryBlock是一條SQL最基本的組成單元,包括三個部分:輸入源,計算過程,輸出。簡單來講一個QueryBlock就是一個子查詢。

為Hive中QueryBlock相關對象的類圖,解釋圖中幾個重要的屬性

  • QB#aliasToSubq(表示QB類的aliasToSubq屬性)儲存子查詢的QB對象,aliasToSubq key值是子查詢的別名
  • QB#qbp 即QBParseInfo儲存一個基本SQL單元中的給個操作部分的AST Tree結構,QBParseInfo#nameToDest這個HashMap儲存查詢單元的輸出,key的形式是inclause-i(由於Hive 支援Multi Insert語句,所以可能有多個輸出),value是對應的ASTNode節點,即TOK_DESTINATION節點。類QBParseInfo其餘 HashMap屬性分別儲存輸出和各個操作的ASTNode節點的對應關係。
  • QBParseInfo#JoinExpr儲存TOK_JOIN節點。QB#QBJoinTree是對Join文法樹的結構化。
  • QB#qbm儲存每個輸入表的元資訊,比如表在HDFS上的路徑,儲存表資料的檔案格式等。
  • QBExpr這個對象是為了表示Union操作。

2.2.2 AST Tree產生QueryBlock

AST Tree產生QueryBlock的過程是一個遞迴的過程,先序遍曆AST Tree,遇到不同的Token節點,儲存到相應的屬性中,主要包含以下幾個過程

  • TOK_QUERY => 建立QB對象,迴圈遞迴子節點
  • TOK_FROM => 將表名文法部分儲存到QB對象的aliasToTabs等屬性中
  • TOK_INSERT => 迴圈遞迴子節點
  • TOK_DESTINATION => 將輸出目標的文法部分儲存在QBParseInfo對象的nameToDest屬性中
  • TOK_SELECT => 分別將查詢運算式的文法部分儲存在destToSelExpr、destToAggregationExprs、destToDistinctFuncExprs三個屬性中
  • TOK_WHERE => 將Where部分的文法儲存在QBParseInfo對象的destToWhereExpr屬性中

最終範例SQL產生兩個QB對象,QB對象的關係如下,QB1是外層查詢,QB2是子查詢

QB1     QB2
2.3 Phase3 邏輯操作符Operator2.3.1 Operator

Hive最終產生的MapReduce任務,Map階段和Reduce階段均由OperatorTree組成。邏輯操作符,就是在Map階段或者Reduce階段完成單一特定的操作。

基本的操作符包括TableScanOperator,SelectOperator,FilterOperator,JoinOperator,GroupByOperator,ReduceSinkOperator

從名字就能猜出各個操作符完成的功能,TableScanOperator從MapReduce架構的Map介面原始輸入表的資料,控制掃描表的資料行數,標記是從原表中取資料。JoinOperator完成Join操作。FilterOperator完成過濾操作

ReduceSinkOperator將Map端的欄位組合序列化為Reduce Key/value, Partition Key,只可能出現在Map階段,同時也標誌著Hive產生的MapReduce程式中Map階段的結束。

Operator在Map Reduce階段之間的資料傳遞都是一個流式的過程。每一個Operator對一行資料完成操作後之後將資料傳遞給childOperator計算。

Operator類的主要屬性和方法如下

  • RowSchema表示Operator的輸出欄位
  • InputObjInspector outputObjInspector解析輸入和輸出欄位
  • processOp接收父Operator傳遞的資料,forward將處理好的資料傳遞給子Operator處理
  • Hive每一行資料經過一個Operator處理之後,會對欄位重新編號,colExprMap記錄每個運算式經過當前Operator處理前後的名稱對應關係,在下一個階段邏輯最佳化階段用來回溯欄位名
  • 由於Hive 的MapReduce程式是一個動態程式,即不確定一個MapReduce Job會進行什麼運算,可能是Join,也可能是GroupBy,所以Operator將所有運行時需要的參數儲存在OperatorDesc 中,OperatorDesc在提交任務前序列化到HDFS上,在MapReduce任務執行前從HDFS讀取並還原序列化。Map階段 OperatorTree在HDFS上的位置在Job.getConf(“hive.exec.plan”) + “/map.xml”

2.3.2 QueryBlock產生Operator Tree

QueryBlock產生Operator Tree就是遍曆上一個過程中產生的QB和QBParseInfo對象的儲存文法的屬性,包含如下幾個步驟:

  • QB#aliasToSubq => 有子查詢,遞迴調用
  • QB#aliasToTabs => TableScanOperator
  • QBParseInfo#joinExpr => QBJoinTree => ReduceSinkOperator + JoinOperator
  • QBParseInfo#destToWhereExpr => FilterOperator
  • QBParseInfo#destToGroupby => ReduceSinkOperator + GroupByOperator
  • QBParseInfo#destToOrderby => ReduceSinkOperator + ExtractOperator

由於Join/GroupBy/OrderBy均需要在Reduce階段完成,所以在產生相應操作的Operator之前都會先產生一個ReduceSinkOperator,將欄位組定序序列化為Reduce Key/value, Partition Key

接下來詳細分析範例SQL產生OperatorTree的過程

先序遍曆上一個階段產生的QB對象

  1. 首先根據子QueryBlock QB2#aliasToTabs {du=dim.user, c=detail.usersequence_client, p=fact.orderpayment}產生TableScanOperator

    TableScanOperator(“dim.user”) TS[0] TableScanOperator(“detail.usersequence_client”) TS[1]        TableScanOperator(“fact.orderpayment”) TS[2]
  2. 先序遍曆QBParseInfo#joinExpr產生QBJoinTree,類QBJoinTree也是一個樹狀結構,QBJoinTree儲存左右表的ASTNode和這個查詢的別名,最終產生的查詢樹如下

    base    /     p    du  /       c        p
  1. 前序走訪QBJoinTree,先產生detail.usersequence_client和fact.orderpayment的Join操作樹

圖中 TS=TableScanOperator RS=ReduceSinkOperator JOIN=JoinOperator

  1. 產生中間表與dim.user的Join操作樹

  1. 根據QB2 QBParseInfo#destToWhereExpr 產生FilterOperator。此時QB2遍曆完成。

中SelectOperator在某些情境下會根據一些條件判斷是否需要解析欄位。

圖中 FIL= FilterOperator SEL= SelectOperator

  1. 根據QB1的QBParseInfo#destToGroupby產生ReduceSinkOperator + GroupByOperator

圖中 GBY= GroupByOperator
GBY[12]是HASH彙總,即在記憶體中通過Hash進行彙總運算

  1. 最終都解析完後,會產生一個FileSinkOperator,將資料寫入HDFS

圖中FS=FileSinkOperator

2.4 Phase4 邏輯層最佳化器

大部分邏輯層最佳化器通過變換OperatorTree,合併作業符,達到減少MapReduce Job,減少shuffle資料量的目的。

名稱

作用

② SimpleFetchOptimizer

最佳化沒有GroupBy運算式的彙總查詢

② MapJoinProcessor

MapJoin,需要SQL中提供hint,0.11版本已不用

② BucketMapJoinOptimizer

BucketMapJoin

② GroupByOptimizer

Map端彙總

① ReduceSinkDeDuplication

合并線性OperatorTree中partition/sort key相同的reduce

① PredicatePushDown

謂詞前置

① CorrelationOptimizer

利用查詢中的相關性,合并有相關性的Job,HIVE-2206

ColumnPruner

欄位剪枝

表格中①的最佳化器均是一個Job幹儘可能多的事情/合并。②的都是減少shuffle資料量,甚至不做Reduce。

CorrelationOptimizer最佳化器非常複雜,都能利用查詢中的相關性,合并有相關性的Job,參考 Hive Correlation Optimizer

對於範例SQL,有兩個最佳化器對其進行最佳化。下面分別介紹這兩個最佳化器的作用,並補充一個最佳化器ReduceSinkDeDuplication的作用

2.4.1 PredicatePushDown最佳化器

斷言判斷提前最佳化器將OperatorTree中的FilterOperator提前到TableScanOperator之後

2.4.2 NonBlockingOpDeDupProc最佳化器

NonBlockingOpDeDupProc最佳化器合并SEL-SEL 或者 FIL-FIL 為一個Operator

2.4.3 ReduceSinkDeDuplication最佳化器

ReduceSinkDeDuplication 可以合并線性相連的兩個RS。實際上CorrelationOptimizer是ReduceSinkDeDuplication的超集,能合并線性和非 線性操作RS,但是Hive先實現的ReduceSinkDeDuplication

譬如下面這條SQL語句

from (select key, value from src group by key, value) s select s.key group by s.key;

經過前面幾個階段之後,會產生如下的OperatorTree,兩個Tree是相連的,這裡沒有畫到一起

這時候遍曆OperatorTree後能發現前前後兩個RS輸出的Key值和PartitionKey如下

 

Key

PartitionKey

childRS

key

key

parentRS

key,value

key,value

ReduceSinkDeDuplication最佳化器檢測到:1. pRS Key完全包含cRS Key,且排序次序一致;2. pRS PartitionKey完全包含cRS PartitionKey。符合最佳化條件,會對執行計畫進行最佳化。

ReduceSinkDeDuplication將childRS和parentheRS與childRS之間的Operator刪掉,保留的RS的Key為key,value欄位,PartitionKey為key欄位。合并後的OperatorTree如下:

2.5 Phase5 OperatorTree產生MapReduce Job的過程

OperatorTree轉化為MapReduce Job的過程分為下面幾個階段

  1. 對輸出表產生MoveTask
  2. 從OperatorTree的其中一個根節點向下深度優先遍曆
  3. ReduceSinkOperator標示Map/Reduce的界限,多個Job間的界限
  4. 遍曆其他根節點,遇過碰到JoinOperator合并MapReduceTask
  5. 產生StatTask更新中繼資料
  6. 剪斷Map與Reduce間的Operator的關係
2.5.1 對輸出表產生MoveTask

由上一步OperatorTree只產生了一個FileSinkOperator,直接產生一個MoveTask,完成將最終產生的HDFS臨時檔案移動到目標表目錄下

MoveTask[Stage-0]Move Operator
2.5.2 開始遍曆

將OperatorTree中的所有根節點儲存在一個toWalk的數組中,迴圈取出數組中的元素(省略QB1,未畫出)

取出最後一個元素TS[p]放入棧 opStack{TS[p]}中

2.5.3 Rule #1 TS% 產生MapReduceTask對象,確定MapWork

發現棧中的元素符合下面規則R1(這裡用python代碼簡單表示)

"".join([t + "%" for t in opStack]) == "TS%"

生 成一個MapReduceTask[Stage-1]對象,MapReduceTask[Stage-1]對象的MapWork屬性儲存Operator 根節點的引用。由於OperatorTree之間之間的Parent Child關係,這個時候MapReduceTask[Stage-1]包含了以TS[p]為根的所有Operator

2.5.4 Rule #2 TS%.*RS% 確定ReduceWork

繼續遍曆TS[p]的子Operator,將子Operator存入棧opStack中
當第一個RS進棧後,即棧opStack = {TS[p], FIL[18], RS[4]}時,就會滿足下面的規則R2

"".join([t + "%" for t in opStack]) == "TS%.*RS%"

這時候在MapReduceTask[Stage-1]對象的ReduceWork屬性儲存JOIN[5]的引用

2.5.5 Rule #3 RS%.*RS% 產生新MapReduceTask對象,切分MapReduceTask

繼續遍曆JOIN[5]的子Operator,將子Operator存入棧opStack中

當第二個RS放入棧時,即當棧opStack = {TS[p], FIL[18], RS[4], JOIN[5], RS[6]}時,就會滿足下面的規則R3

"".join([t + "%" for t in opStack]) == “RS%.*RS%” //迴圈遍曆opStack的每一個尾碼數組

這 時候建立一個新的MapReduceTask[Stage-2]對象,將OperatorTree從JOIN[5]和RS[6]之間剪開,並為 JOIN[5]產生一個子OperatorFS[19],RS[6]產生一個TS[20],MapReduceTask[Stage-2]對象的 MapWork屬性儲存TS[20]的引用。

新產生的FS[19]將中間資料落地,儲存在HDFS臨時檔案中。

繼續遍曆RS[6]的子Operator,將子Operator存入棧opStack中

當opStack = {TS[p], FIL[18], RS[4], JOIN[5], RS[6], JOIN[8], SEL[10], GBY[12], RS[13]}時,又會滿足R3規則

同理產生MapReduceTask[Stage-3]對象,並切開 Stage-2 和 Stage-3 的OperatorTree

2.5.6 R4 FS% 串連MapReduceTask與MoveTask

最 終將所有子Operator存入棧中之後,opStack = {TS[p], FIL[18], RS[4], JOIN[5], RS[6], JOIN[8], SEL[10], GBY[12], RS[13], GBY[14], SEL[15], FS[17]}滿足規則R4

"".join([t + "%" for t in opStack]) == “FS%”

這時候將MoveTask與MapReduceTask[Stage-3]串連起來,並產生一個StatsTask,修改表的元資訊

2.5.7 合并Stage

此時並沒有結束,還有兩個根節點沒有遍曆。

將opStack棧清空,將toWalk的第二個元素加入棧。會發現opStack = {TS[du]}繼續滿足R1 TS%,產生MapReduceTask[Stage-5]

繼續從TS[du]向下遍曆,當opStack={TS[du], RS[7]}時,滿足規則R2 TS%.*RS%

此 時將JOIN[8]儲存為MapReduceTask[Stage-5]的ReduceWork時,發現在一個Map對象儲存的Operator與 MapReduceWork對象關係的Map<operator, mapreducework="">對象中發現,JOIN[8]已經存在。此時將MapReduceTask[Stage-2]和 MapReduceTask[Stage-5]合并為一個MapReduceTask

同理從最後一個根節點TS[c]開始遍曆,也會對MapReduceTask進行合并

2.5.8 切分Map Reduce階段

最後一個階段,將MapWork和ReduceWork中的OperatorTree以RS為界限剪開

2.5.9 OperatorTree產生MapReduceTask全貌

最終共產生3個MapReduceTask,如

2.6 Phase6 物理層最佳化器

這裡不詳細介紹每個最佳化器的原理,單獨介紹一下MapJoin的最佳化器

名稱

作用

Vectorizer

HIVE-4160,將在0.13中發布

SortMergeJoinResolver

與bucket配合,類似于歸並排序

SamplingOptimizer

並行order by最佳化器,在0.12中發布

CommonJoinResolver + MapJoinResolver

MapJoin最佳化器

2.6.1 MapJoin原理

MapJoin簡單說就是在Map階段將小表讀入記憶體,順序掃描大表完成Join。

是Hive MapJoin的原理圖,出自Facebook工程師Liyin Tang的一篇介紹Join最佳化的slice,可以看出MapJoin分為兩個階段:

  1. 通過MapReduce Local Task,將小表讀入記憶體,產生HashTableFiles上傳至Distributed Cache中,這裡會對HashTableFiles進行壓縮。

  2. MapReduce Job在Map階段,每個Mapper從Distributed Cache讀取HashTableFiles到記憶體中,順序掃描大表,在Map階段直接進行Join,將資料傳遞給下一個MapReduce任務。

如果Join的兩張表一張表是暫存資料表,就會產生一個ConditionalTask,在運行期間判斷是否使用MapJoin

2.6.2 CommonJoinResolver最佳化器

CommonJoinResolver最佳化器就是將CommonJoin轉化為MapJoin,轉化過程如下

  1. 深度優先遍曆Task Tree
  2. 找到JoinOperator,判斷左右表資料量大小
  3. 對與小表 + 大表 => MapJoinTask,對於小/大表 + 中間表 => ConditionalTask

遍 曆上一個階段產生的MapReduce任務,發現MapReduceTask[Stage-2] JOIN[8]中有一張表為暫存資料表,先對Stage-2 進行深度拷貝(由於需要保留原始執行計畫為Backup Plan,所以這裡將執行計畫拷貝了一份),產生一個MapJoinOperator替代JoinOperator,然後產生一個 MapReduceLocalWork讀取小表產生HashTableFiles上傳至DistributedCache中。

MapReduceTask經過變換後的執行計畫如所示

2.6.3 MapJoinResolver最佳化器

MapJoinResolver最佳化器遍曆Task Tree,將所有有local work的MapReduceTask拆成兩個Task

最終MapJoinResolver處理完之後,執行計畫如所示

3、Hive SQL編譯過程的設計

從上述整個SQL編譯的過程,可以看出編譯過程的設計有幾個優點值得學習和借鑒

  • 使用Antlr開源軟體定義程式文法規則,大大簡化了詞法和文法的編譯解析過程,僅僅需要維護一份文法檔案即可。
  • 整體思路很清晰,分階段的設計使整個編譯過程代碼容易維護,使得後續各種最佳化器方便的以可插拔的方式開關,譬如Hive 0.13最新的特性Vectorization和對Tez引擎的支援都是可插拔的。
  • 每個Operator只完成單一的功能,簡化了整個MapReduce程式。
4、社區發展方向

Hive依然在迅速的發展中,為了提升Hive的效能,hortonworks公司主導的Stinger計劃提出了一系列對Hive的改進,比較重要的改進有:

  • Vectorization - 使Hive從單行單行處理資料改為批量處理方式,大大提升了指令流水線和緩衝的利用率
  • Hive on Tez - 將Hive底層的MapReduce計算架構替換為Tez計算架構。Tez不僅可以支援多Reduce階段的任務MRR,還可以一次性提交執行計畫,因而能更好的分配資源。
  • Cost Based Optimizer - 使Hive能夠自動選擇最優的Join順序,提高查詢速度
  • Implement insert, update, and delete in Hive with full ACID support - 支援表按主鍵的累加式更新

我們也將跟進社區的發展,結合自身的業務需要,提升Hive型ETL流程的效能

5、參考

Antlr: http://www.antlr.org/
Wiki Antlr介紹: http://en.wikipedia.org/wiki/ANTLR
Hive Wiki: https://cwiki.apache.org/confluence/display/Hive/Home
HiveSQL編譯過程: http://www.slideshare.net/recruitcojp/internal-hive
Join Optimization in Hive: Join Strategies in Hive from the 2011 Hadoop Summit (Liyin Tang, Namit Jain)
Hive Design Docs: https://cwiki.apache.org/confluence/display/Hive/DesignDocs

原文地址: http://tech.meituan.com/hive-sql-to-mapreduce.html

Hive SQL 編譯過程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.