hive 基本原理

一、組件:
  元存儲(Metastore )-存儲「系統目錄以及關於表、列、分區等的元數據」的組件。
  驅動(Driver )- 控制 HiveQL 生命週期的組件,當 HiveQL 查詢穿過 Hive時。該驅動管理着會話句柄以及任何會話的統計。
  查詢編譯器(Query Compiler) - 是一個組件,將HiveQL編譯成有向無環圖(directed acyclic graph, DAG)形式的map/reduce任務。
  執行引擎 Execution Engine - 是一個組件,依相依性順序(dependency order)執行由編譯器產生的任務。
  Hive 服務器 HiveServer - 一個提供「健壯的接口(thrift interface )、JDBC/ODBC 服務器以及提供一種整合 Hive 和其它應用的」組件。
  客戶端組件 -相似命令行接口CLI(Command Line Interface), web UI 以及JDBC/ODBC驅動。包含了正反序列化(SerDe)以及對象觀察器(ObjectInspector)接口的可擴展接口,相似於前述用戶定義函 數 UDF (User Defined Function)以及用戶定義聚合函數UDAF(User Defined AggregateFunction)接口,容許用戶定義本身的列函數。
html


二、執行的過程:
  HiveQL經過CLI/web UI或者thrift 、 odbc 或 jdbc接口的外部接口提交,通過complier編譯器,運用Metastore中的雲數據進行類型檢測和語法分析,生成一個邏輯方案(logical plan),而後經過簡單的優化處理,產生一個以有向無環圖DAG數據結構形式展示的map-reduce任務
web


三、元存儲(Metastore)
  存儲列全部關於表、表的分區、模式、列及其類型、表地址等的表的元數據,能夠經過thrift接口查詢獲得,因爲須要快速的提供到編譯器中,因此使用RDBMS
緩存

四、查詢編譯器(query complier)
  用雲存儲中的元數據來生成執行計劃,步驟以下:
    1).解析(parse)-anlr解析其生成語法樹AST(hibernate也是這個):將HQL轉化爲抽象語法樹AST
    2).類型檢查和語法分析(type checking and semantic analysis):將抽象語法樹轉換此查詢塊(query block tree),並將查詢塊轉換成邏輯查詢計劃(logic plan Generator);
    3).優化(optimization):重寫查詢計劃(logical optimizer)-->將邏輯查詢計劃轉成物理計劃(physical plan generator)-->選擇最佳的join策略(physical optimizer)
服務器

  parse   sa    lpg       lo        ppg       po
hql------->AST------>QB----->OP TREE------->OP TREE------->task tree------->task tree
數據結構

  首先進行hql語句解析,構造一顆AST 樹,從AST樹中獲得QueryBlock,再將QB轉爲對應的操做符,生成邏輯查詢計劃,對邏輯查詢計劃進行優化(謂詞下推),生成物理查詢計劃,對物 理查詢計劃進行優化(MapJoinResolver/SkewJoinResolver/CommonJoinResolver),獲得最後的執行計 劃。app

  MapJoinResolver:將小表 的MR結果放入HashTableFiles-->DistributedCache,大表從分佈式緩存中取得數據進行join;當hash數據較 大時,分佈式緩存查詢效率下降,同時大表的Map都>在等待hash files;因此對其進行列優化處理小表的結果放到DC中進行壓縮和更新,大表遍歷時從DC中取出tar包>,而後解壓讀取本地的hash files分佈式


  Hive完成列如下轉換,做爲優化階段的一部分:
    1).列剪輯(column pruning):查詢處理中惟一須要的列確實從行中投射出去
    2).謂語下推(Predicate pushdown):將只於一張表有關的過濾操做下推至TableScanOperator以後,
    3).分區剪輯(Partition pruning):過濾掉分區上不符合條件的字段
    4).Map 端的鏈接(Map side joins):當join的表很小時,在map段先複製它而後再進行join,格式以下:
      SELECT /*+ MAPJOIN(t2) */ t1.c1, t2.c1 FROM t1 JOIN t2 ON(t1.c2 = t2.c2);
      由hive.mapjoin.size.key以及hive.mapjoin.cache.numrows控制「任什麼時候間保存在內存中的」表中行的數量,以及提供給系統聯合鍵的大小
    5).鏈接再排序(Join reordering):把較小的表保存在內存中,較大的表進行遍歷操做,保證系統內存不溢出
ide

五、MapJoin的進一步優化
  1).數據再分區以把控GROUPBY造成的非對稱(skews):用兩個MapReduce來作,第一個階段將數據隨機分發(或者按 DISTINCT列分發在DISTINCT聚合的狀況下)至reducers,而且計算聚合值;而後這些聚合結果按照GROUP BY 列分發給在第二個Reducer;
函數

     set hive.groupby.skewindata= true ;
    SELECT t1.c1, sum(t1.c2)
    FROM t1
    GROUP BY t1.c1;
優化

  2).mappers中的基於哈希的局部聚合:至關於combiner,在map端內存中進行聚合,而後發送給reducers,參數 hive.map.aggr.hash.percentmemory說明了mapper 內存中可用於把控哈希表那部分的數量。如0.5能確保哈希表大小一旦超過用於mapper的最大內存的一半,存儲在那兒的部分聚合就被髮送到 reducers了。hive.map.aggr.hash.min.reduction參數一樣也用來控制用於mappers的內存數量

 

六、執行引擎(execution engine):

  按照任務的依賴關係序列來執行


7.其它優化:
  1).Left Semi Join實現in/exists子查詢:
    SELECT A.* FROM A LEFT SEMI JOIN B ON(A.KEY = B.KEY AND B.KEY > 100);
    等同於SELECT A.* FROM A WHERE A.KEY IN(SELECT B.KEY FORM B WHERE B.KEY > 100);
    做用:map端用group by減小流入reduce端的數據量

  2).Bucket Map Join:
    set hive.optimize.bucketmapjoin = true;
    和Map join一塊兒工做;
    全部join的表都作列分桶,同時大表桶的數量是小表桶的整數倍;
    作bucket的列必須是join的列;

    SELECT /*+MAPJOIN(a,c)*/ a.*, b.*, c.*
    a join b on a.key = b.key
    join c on a.key=c.key;
    在現實的生產環境中,會有成百上千個buckets;

  3).Skew join:
    join時數據傾斜,形成Reduce端OOM
    set hive.optimize.skewjoin = true;
    set hive.skewjoin.key = 閥值;
    當JOIN獲得的map超過閥值時,將內存中的a-k1/b-k1數據分別存入hdfs中,而後遍歷完後再對hdfs上的兩塊數據作Map Join,和其它key一塊兒組成最後結果

 

引入:http://www.cnblogs.com/uttu/archive/2013/02/28/2936953.html

相關文章
相關標籤/搜索