1. 基本概念
Hive是由Facebook在2007年8月開始開發,並於2008年8月開源(https://issues.apache.org/jira/browse/HADOOP-3601)。它是建立在Hadoop上的數據倉庫工具,它可以對存儲在HDFS、HBase、PG等存儲系統中的文件進行結構化分析等操作。
Hive提供了以下功能:
1) 提供類SQL語言(HQL),可以很方便的做ETL操作
2) 數據可以存儲在多個不同的存儲系統,可以使用多種存儲類型
3) 查詢執行是通過MapReduce實現
4) 提供豐富的函數,普通函數(split等)、分析函數(sum等)、表級函數(row_number等)
2. 產生背景
在Hadoop出現以前,是關係型數據庫的天下,SQL語言成爲很多人的必備技能。但是,隨着數據量的日益增長,單機存儲計算已然滿足不了海量數據的分析需求。並行計算框架MapReduce隨之產生,並得到了迅猛的發展,它可以對數據並行分析處理,使得海量數據的快速分析成爲可能。但是,編寫MR程序卻不是一件很容易的事情,Hive隨之而來,它可以將SQL語言自動轉換成MR程序去執行,可以讓使用者只關注自己的業務邏輯,如此方便的神器自然得到了很多人的青睞,尤其是原來習慣編寫SQL的人,hive得到的迅猛發展。
3. TDW之Hive歷史
瞭解我們公司的Hive,不得不說TDW(Tencent distributed Data Warehouse)的歷史。我們是在2009年7月,成立TDW項目組,並啓動技術架構預言。同年12月,確定TDW技術架構方案,並開始投入開發。2010年6月TDW 0.1版本發佈,具備數據倉庫基礎功能。隨後,不斷完善功能、調優。2011年7月,TDW IDE發佈,提高了TDW的易用性的同時,大大促進了TDW在公司的普及。
TDW是公司級數據平臺,基於share-nothing架構,具有高可用性和高可伸縮性。業務涉及公司各個BG,目前擁有8800臺集羣規模,主要包括查詢引擎,計算引擎和存儲引擎。這其中的查詢引擎就是指的Hive(這裏指離線計算,實時計算使用的EasyCount系統),Hive在TDW中所處的位置如下圖所示。
(老架構)
我們的Hive是在社區版本的基礎上,做了大量的優化,根據業務特點做了大量的個性化定製,如元數據庫的重新設計、各類函數的實現、List/Range分區的優化設計等,使得平臺的穩定性、性能和易用性都有顯著提高。
4. 執行流程
下面將說下hive的工作原理。
工作流程:
Hive提供3種用戶接口:CLI(命令行模式),Client(交互模式),WebUI(網頁訪問)。TDW的使用方式是後臺啓動hiveserver,然後,使用PLC去連接HiveServer,執行相應的SQL,並返回結果。PLC是TDW自己用python實現的連接hiveServer的腳本。
如圖所示,IDE/Lhotse通過PLC連接到HiveServer(通過Thrift實現),HiveServer會去解析sql,通過MR計算相應結果,然後返回。下面將詳細介紹Hive是怎樣解析SQL語句,並執行任務的。
詳細流程:
HQL語句主要分爲四種:DDL(數據定義語言)、DCL(數據控制語言)、DML(數據操作語言)、DQL(數據查詢語言)。
DDL:創建/刪除表,創建/刪除分區,顯示函數等操作。
DCL:創建/刪除用戶,授予/撤銷權限等操作。
DML:insert/update等操作。
DQL:select操作。
DDL和DCL語句執行流程很簡單,無須執行MR作業,只需要對元數據(metaDB)、HDFS、tPG庫進行相應的操作即可完成。DML和DQL是一般都需要執行MR作業,除非一些特殊的語句進行優化後,無須執行MR(如select * from limit語句等)。
DML和DQL都比較複雜,它會將HQL語句轉換成一個或者多個MR作業執行,得到最終結果。
HQL語句的執行過程總的概括爲:HQL->AST->OpT->TaskT->執行->返回結果。下面我們以“SELECT a, sum(b), count(distinct c) FROM test::a_roncen1 GROUP BY a”爲例,對Hive執行流程進行說明。(表a_roncen1的定義爲CREATE TABLE a_roncen1(a BIGINT,bBIGINT,c STRING))
(1) HQL->AST
AST是指抽象語法樹,Hive使用開源的語法分析器Antlr對HQL進行解析。可以在Hive.g文件中定義新的語法。上述語句,則會轉爲以下AST樹。
(2) AST->OpT
OpT是指算子樹,這個過程比較負責,也是hive的核心內容之一。大概分爲3步:
① 對AST樹進行深度優先遍歷,遇到相應的標籤,將其存儲到相應的數據結構,供後續操作。
② 根據第一步所得的數據結構,查找元數據和操作HDFS,得到對應的相關信息,並存儲。
③ 根據上兩部所得的信息,生成最後的OpT。
如上圖,
① 進行深度優先遍歷:
遇到TOK_FROM:將其子樹作爲HQL的數據源;
遇到TOK_DESTINATION:將其作爲結果文件的存放位置;
遇到TOK_SELECT:保存選擇列的信息;
遇到TOK_GROUPBY:保存group by列的信息。
② 讀取元數據信息:
將數據源信息(表a_roncen1信息),結果文件信息(存放HDFS臨時目錄)等存放到相應的數據結構。
③ 根據上述信息生成對應的OpT:
數據源表(TOK_FROM)會生成“表掃描算子(TableScanOperator)”;
選擇列會生成“選擇算子(SelectOperator)”;
Group by列比較複雜,會用到reduce功能,生成“選擇算子”、“輸出算子(ReduceSinkOperator)”和“分組算子(GroupByOperator)”三個算子。
(3) OpT->TaskT
TaskT是指任務樹,每個任務是hive執行的邏輯單元,任務樹在這裏可以簡單理解爲一個MR的job。
Hive會根據算子樹,生成對應的任務樹,上述例子比較簡單,將此算子樹生成對應的MRjob。
舉個複雜的例子:SELECT a,sum(b) FROM (SELECT a, sum(b) AS b, count(distinct c) AS c FROM test::a_roncen1 GROUP BY a) sub WHERE sub.a=0 GROUP BY a ;
這條HQL生成的TaskT如下所示,是兩個MRjob,兩個作業之間使用HDFS作爲中間數據存儲。
(4) TaskT執行
生成完TaskT後,就開始執行任務了。有依賴關係的job,必須要等其所有的父job執行完後,當前job纔會開始執行。
Hive會將當前job的OpT序列化到HDFS上,然後,將job提交到MR,當執行Map和Reduce時,會將序列化的OpT反序列化,對每一行數據,依次執行每個算子。數據就像流水一樣,沿着算子樹往下流。
(5) 返回結果
如果是DQL語句,則會將結果存放在HDFS的臨時目錄下,然後,Hiveserver會去讀取臨時目錄下的文件,並返回給客戶端。
5. 總結
TDW的Hive經歷很多年的打磨,已經日趨成熟穩定。但是,隨着時間的推移,我們的Hive也暴露出很多問題,如與社區的Hive相差太大,社區的很多好的功能(向量查詢引擎、基於代價查詢優化等)都沒有引進;Hive的多個job之間使用HDFS作爲中間結果存儲媒介,嚴重影響效率等問題。
針對第一個問題,我們在評估將社區Hive的適用我們公司業務的功能整合到TDW的Hive上。
針對第二個問題,我們基於社區的SparkSQL上,做了很多的性能優化和個性化定製,和Hive的HQL語句已經實現了很好的兼容,可以顯著提高SQL執行效率和系統穩定性。
TDW平臺會不斷對平臺進行優化和革新,一心致力於爲用戶提供穩定、優質、可靠的數據服務。