1. 程式人生 > 其它 >大資料倉庫Hive原理與架構

大資料倉庫Hive原理與架構

前面講到,MapReduce計算模型可以解決絕大多數的資料分析與資料探勘任務,那麼對於如下我們常見的一條SQL分析語句,MapReduce如何程式設計實現?

SELECT pageid, age, count(1) FROM pv_users GROUP BY pageid, age;

這是一條非常常見的SQL統計分析語句,統計不同年齡的使用者訪問不同網頁的興趣偏好,對於產品運營和設計很有價值。具體資料輸入和執行結果如下圖示例。

group by輸入輸出示例

左邊是要分析的資料表,右邊是分析結果。實際上把左邊表相同的行累計求和,就得到右邊的表了,看起來跟WordCount的計算很一樣。確實也是這樣,我們看下這條SQL語句的MapReduce的計算過程,map和reduce函式的輸入輸出以及函式處理過程分別是什麼樣。

首先,看下map函式的輸入key和value,key不重要,忽略掉,value就是左邊表中每一行的資料,<1, 25>這樣。map函式的輸出就是以輸入的value作為key,value統一設為1,<<1, 25>, 1>這樣。

map函式的輸出經過shuffle以後,相同的key及其對應的value被放在一起組成一個<key,value集合>,作為輸入交給reduce函式處理。如<<2, 25>, 1>被map函式輸出兩次,那麼到了reduce這裡,就變成輸入<<2, 25>, <1, 1>>,key是<2, 25>, value集合是<1, 1>。在reduce函式內部,value集合裡所有的數字被相加,然後輸出。reduce的輸出就是<<2, 25>, 2>。

計算過程如下圖示例。

group by的MapReduce計算過程示例

這樣一條很有實用價值的SQL就這樣被很簡單的MapReduce計算過程處理好了。在資料倉庫中,SQL是最常用的分析工具,那麼有沒有能夠自動將SQL生成MapReduce程式碼的工具呢?這個工具就是Hadoop大資料倉庫Hive。

Hive能夠直接處理使用者輸入的SQL語句(Hive的SQL語法和資料庫標準SQL略有不同),呼叫MapReduce計算框架完成資料分析操作。具體架構如下圖。

Hive架構

使用者通過Hive的Client(Hive的命令列工具,JDBC等)向Hive提交SQL命令。如果是建立資料表的DDL語句,Hive就會通過執行引擎Driver將資料表的資訊記錄在Metastore元件中,這個元件通常用一個關係資料庫實現,記錄表名、欄位名、欄位型別、關聯hdfs檔案路徑等這些資料庫的meta資訊(元資訊)。

如果使用者提交的是查詢分析資料的DQL語句,Driver就會將該語句提交給自己的編譯器Compiler進行語法分析、語法解析、語法優化等一系列操作,最後買QQ地圖生成一個MapReduce執行計劃。然後根據該執行計劃生成一個MapReduce的作業,提交給Hadoop MapReduce計算框架處理。

對於一個較簡單的SQL命令,比如:

SELECT * FROM status_updates WHERE status LIKE ‘michael jackson’;

其對應的Hive執行計劃如下圖。

Hive執行計劃示例

Hive內部預置了很多函式,Hive的執行計劃就是根據SQL語句生成這些函式的DAG(有向無環圖),然後封裝進MapReduce的map和reduce函式中。這個例子中,map函式呼叫了三個Hive內建函式TableScanOpoerator、FilterOperator、FileOutputOperator,就完成了map計算,而且無需reduce函式。

除了上面這些簡單的聚合(group by)、過濾(where)操作,Hive還能執行連線(join on)操作。上面例子中,pv_users表的資料在實際中是無法直接得到的,因為pageid資料來自使用者訪問日誌,每個使用者進行一次頁面瀏覽,就會生成一條訪問記錄,儲存在page_view表中。而年齡age資訊則記錄在使用者表user中。如下圖。

page_view表和user表示例

這兩張表都有一個相同的欄位userid,根據這個欄位可以將兩張表連線起來,生成前面的pv_users表,SQL命令如下:

SELECT pv.pageid, u.age FROM page_view pv JOIN user u ON (pv.userid = u.userid);

同樣,這個SQL命令也可以轉化為MapReduce計算,如下圖。

join的MapReduce計算過程示例

join的MapReduce計算過程和前面的group by稍有不同,因為join涉及兩張表,來自兩個檔案(夾),所以需要在map輸出的時候進行標記,比如來自第一張表的輸出value就記錄為<1, X>,這裡的1表示資料來自第一張表。這樣經過shuffle以後,相同的key被輸入到同一個reduce函式,就可以根據表的標記對value資料求笛卡爾積,輸出就join的結果。

在實踐中,工程師並不需要經常編寫MapReduce程式,因為網站最主要的大資料處理就是SQL分析,在Facebook,據說90%以上的MapReduce任務都是Hive產生的。Hive在大資料應用中的作用非常重要。