分布式离线计算—HiveSQL
原文作者:極客教程
原文地址:Hive 簡(jiǎn)介
目錄
MapReduce實(shí)現(xiàn)SQL的原理
Hive的架構(gòu)
Hive如何實(shí)現(xiàn)join操作
總結(jié)
Hive 簡(jiǎn)介,Hive是Hadoop大數(shù)據(jù)倉庫Hive。在數(shù)據(jù)倉庫中,SQL是最常用的分析工具,既然一條SQL可以通過MapReduce程序?qū)崿F(xiàn),那么有沒有工具能夠自動(dòng)將SQL生成MapReduce代碼呢,答案就是Hive。
MapReduce的出現(xiàn)大大簡(jiǎn)化了大數(shù)據(jù)編程的難度,使得大數(shù)據(jù)計(jì)算不再是高不可攀的技術(shù)圣殿,普通工程師也能使用MapReduce開發(fā)大數(shù)據(jù)程序。但是對(duì)于經(jīng)常需要進(jìn)行大數(shù)據(jù)計(jì)算的人,比如從事研究商業(yè)智能(BI)的數(shù)據(jù)分析師來說,他們通常使用SQL進(jìn)行大數(shù)據(jù)分析和統(tǒng)計(jì),MapReduce編程還是有一定的門檻。而且如果每次統(tǒng)計(jì)和分析都開發(fā)相應(yīng)的MapReduce程序,成本也確實(shí)太高了。那么有沒有更簡(jiǎn)單的辦法,可以直接將SQL運(yùn)行在大數(shù)據(jù)平臺(tái)上呢?
在給出答案前,我們先看看如何用MapReduce實(shí)現(xiàn)SQL數(shù)據(jù)分析。
MapReduce實(shí)現(xiàn)SQL的原理
對(duì)于常見的一條SQL分析語句,MapReduce如何編程實(shí)現(xiàn)?
SELECT pageid, age, count(1) FROM pv_users GROUP BY pageid, age;這是一條非常常見的SQL統(tǒng)計(jì)分析語句,統(tǒng)計(jì)不同年齡的用戶訪問不同網(wǎng)頁的興趣偏好,對(duì)于產(chǎn)品運(yùn)營(yíng)和設(shè)計(jì)很有價(jià)值。具體數(shù)據(jù)輸入和執(zhí)行結(jié)果請(qǐng)看下面的圖示。
?
左邊是要分析的數(shù)據(jù)表,右邊是分析結(jié)果。實(shí)際上把左邊表相同的行進(jìn)行累計(jì)求和,就得到右邊的表了,看起來跟WordCount的計(jì)算很相似。確實(shí)也是這樣,我們看下這條SQL語句的MapReduce的計(jì)算過程,按照MapReduce編程模型,map和reduce函數(shù)的輸入輸出以及函數(shù)處理過程分別是什么。首先,看下map函數(shù)的輸入Key和Value,我們主要看Value。Value就是左邊表中每一行的數(shù)據(jù),比如<1, 25>這樣。map函數(shù)的輸出就是以輸入的Value作為Key,Value統(tǒng)一設(shè)為1,比如<<1, 25>, 1>這樣。map函數(shù)的輸出經(jīng)過shuffle以后,相同的Key及其對(duì)應(yīng)的Value被放在一起組成一個(gè)<Key, Value集合>,作為輸入交給reduce函數(shù)處理。比如<<2, 25>, 1>被map函數(shù)輸出兩次,那么到了reduce這里,就變成輸入<<2, 25>,?<1, 1>>,這里的Key是<2, 25>,Value集合是<1, 1>。在reduce函數(shù)內(nèi)部,Value集合里所有的數(shù)字被相加,然后輸出。所以reduce的輸出就是<<2, 25>, 2>。講起來有點(diǎn)拗口,我把這個(gè)過程畫成了一張圖,看起來就清楚多了。
這樣一條很有實(shí)用價(jià)值的SQL就被很簡(jiǎn)單的MapReduce計(jì)算過程處理好了。在數(shù)據(jù)倉庫中,SQL是最常用的分析工具,既然一條SQL可以通過MapReduce程序?qū)崿F(xiàn),那么有沒有工具能夠自動(dòng)將SQL生成MapReduce代碼呢?這樣數(shù)據(jù)分析師只要輸入SQL,就可以自動(dòng)生成MapReduce可執(zhí)行的代碼,然后提交Hadoop執(zhí)行,也就完美解決了我們最開始提出的問題。問題的答案,也就是這個(gè)神奇的工具就是Hadoop大數(shù)據(jù)倉庫Hive。
Hive的架構(gòu)
Hive能夠直接處理我們輸入的SQL語句(Hive的SQL語法和數(shù)據(jù)庫標(biāo)準(zhǔn)SQL略有不同),調(diào)用MapReduce計(jì)算框架完成數(shù)據(jù)分析操作。下面是它的架構(gòu)圖,我們結(jié)合架構(gòu)圖來看看Hive是如何實(shí)現(xiàn)將SQL生成MapReduce可執(zhí)行代碼的。
?
我們通過Hive的Client(Hive的命令行工具,JDBC等)向Hive提交SQL命令。如果是創(chuàng)建數(shù)據(jù)表的DDL(數(shù)據(jù)定義語言),Hive就會(huì)通過執(zhí)行引擎Driver將數(shù)據(jù)表的信息記錄在Metastore元數(shù)據(jù)組件中,這個(gè)組件通常用一個(gè)關(guān)系數(shù)據(jù)庫實(shí)現(xiàn),記錄表名、字段名、字段類型、關(guān)聯(lián)HDFS文件路徑等這些數(shù)據(jù)庫的Meta信息(元信息)。如果我們提交的是查詢分析數(shù)據(jù)的DQL(數(shù)據(jù)查詢語句),Driver就會(huì)將該語句提交給自己的編譯器Compiler進(jìn)行語法分析、語法解析、語法優(yōu)化等一系列操作,最后生成一個(gè)MapReduce執(zhí)行計(jì)劃。然后根據(jù)執(zhí)行計(jì)劃生成一個(gè)MapReduce的作業(yè),提交給Hadoop MapReduce計(jì)算框架處理。對(duì)于一個(gè)較簡(jiǎn)單的SQL命令,比如:
SELECT * FROM status_updates WHERE status LIKE ‘michael jackson’;它對(duì)應(yīng)的Hive執(zhí)行計(jì)劃如下圖。
Hive內(nèi)部預(yù)置了很多函數(shù),Hive的執(zhí)行計(jì)劃就是根據(jù)SQL語句生成這些函數(shù)的DAG(有向無環(huán)圖),然后封裝進(jìn)MapReduce的map和reduce函數(shù)中。這個(gè)例子中,map函數(shù)調(diào)用了三個(gè)Hive內(nèi)置函數(shù)TableScanOperator、FilterOperator、FileOutputOperator,就完成了map計(jì)算,而且無需reduce函數(shù)。
?
Hive如何實(shí)現(xiàn)join操作
除了上面這些簡(jiǎn)單的聚合(group by)、過濾(where)操作,Hive還能執(zhí)行連接(join on)操作。文章開頭的例子中,pv_users表的數(shù)據(jù)在實(shí)際中是無法直接得到的,因?yàn)閜ageid數(shù)據(jù)來自用戶訪問日志,每個(gè)用戶進(jìn)行一次頁面瀏覽,就會(huì)生成一條訪問記錄,保存在page_view表中。而age年齡信息則記錄在用戶表user中。
?
這兩張表都有一個(gè)相同的字段userid,根據(jù)這個(gè)字段可以將兩張表連接起來,生成前面例子的pv_users表,SQL命令是
SELECT pv.pageid, u.age FROM page_view pv JOIN user u ON (pv.userid = u.userid);同樣,這個(gè)SQL命令也可以轉(zhuǎn)化為MapReduce計(jì)算,連接的過程如下圖所示。
從圖上看,join的MapReduce計(jì)算過程和前面的group by稍有不同,因?yàn)閖oin涉及兩張表,來自兩個(gè)文件(夾),所以需要在map輸出的時(shí)候進(jìn)行標(biāo)記,比如來自第一張表的輸出Value就記錄為<1, X>,這里的1表示數(shù)據(jù)來自第一張表。這樣經(jīng)過shuffle以后,相同的Key被輸入到同一個(gè)reduce函數(shù),就可以根據(jù)表的標(biāo)記對(duì)Value數(shù)據(jù)求笛卡爾積,用第一張表的每條記錄和第二張表的每條記錄連接,輸出就是join的結(jié)果。所以我們?nèi)绻蜷_Hive的源代碼,看join相關(guān)的代碼,會(huì)看到一個(gè)兩層for循環(huán),對(duì)來自兩張表的記錄進(jìn)行連接操作。
總結(jié)
在實(shí)踐中,工程師其實(shí)并不需要經(jīng)常編寫MapReduce程序,因?yàn)榫W(wǎng)站最主要的大數(shù)據(jù)處理就是SQL分析,也因此Hive在大數(shù)據(jù)應(yīng)用中的作用非常重要。后面隨著Hive的普及,我們對(duì)于在Hadoop上執(zhí)行SQL的需求越加強(qiáng)烈,對(duì)大數(shù)據(jù)SQL的應(yīng)用場(chǎng)景也多樣化起來,于是又開發(fā)了各種大數(shù)據(jù)SQL引擎。
Cloudera開發(fā)了Impala,這是一種運(yùn)行在HDFS上的MPP架構(gòu)的SQL引擎。和MapReduce啟動(dòng)Map和Reduce兩種執(zhí)行進(jìn)程,將計(jì)算過程分成兩個(gè)階段進(jìn)行計(jì)算不同,Impala在所有DataNode服務(wù)器上部署相同的Impalad進(jìn)程,多個(gè)Impalad進(jìn)程相互協(xié)作,共同完成SQL計(jì)算。在一些統(tǒng)計(jì)場(chǎng)景中,Impala可以做到毫秒級(jí)的計(jì)算速度。
后來Spark出道以后,也迅速推出了自己的SQL引擎Shark,也就是后來的Spark SQL,將SQL語句解析成Spark的執(zhí)行計(jì)劃,在Spark上執(zhí)行。由于Spark比MapReduce快很多,Spark SQL也相應(yīng)比Hive快很多,并且隨著Spark的普及,Spark SQL也逐漸被人們接受。后來Hive推出了Hive on Spark,將Hive的執(zhí)行計(jì)劃轉(zhuǎn)換成Spark的計(jì)算模型,當(dāng)然這是后話了。
此外,我們還希望在NoSQL的數(shù)據(jù)庫上執(zhí)行SQL,畢竟SQL發(fā)展了幾十年,積累了龐大的用戶群體,很多人習(xí)慣了用SQL解決問題。于是Saleforce推出了Phoenix,一個(gè)執(zhí)行在HBase上的SQL引擎。
Hive本身的技術(shù)架構(gòu)其實(shí)并沒有什么創(chuàng)新,數(shù)據(jù)庫相關(guān)的技術(shù)和架構(gòu)已經(jīng)非常成熟,只要將這些技術(shù)架構(gòu)應(yīng)用到MapReduce上就得到了Hadoop大數(shù)據(jù)倉庫Hive。但是想到將兩種技術(shù)嫁接到一起,卻是極具創(chuàng)新性的,通過嫁接產(chǎn)生出的Hive可以極大降低大數(shù)據(jù)的應(yīng)用門檻,也使Hadoop大數(shù)據(jù)技術(shù)得到大規(guī)模普及。
總結(jié)
以上是生活随笔為你收集整理的分布式离线计算—HiveSQL的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 常用框架概览
- 下一篇: 监控工具—Prometheus—监控Re