序言:在大數據領域存在一個現象,那就是組件繁多,粗略估計一下輕鬆超過20種。若是你是初學者,瞬間就會蒙圈,不知道力往哪裏使。那麼,爲何會出現這種現象呢?在本文的開頭筆者就簡單的闡述一下這種現象出現的緣由,相信對一直陪伴筆者的你會有所幫助。mysql
行文思路
大數據組件來源sql
Hive簡介數據庫
定義apache
hive特色網絡
hive基本語法架構
Hive原理併發
hive架構圖oracle
hive內核負載均衡
hive底層存儲框架
hive程序執行過程
hive元數據存儲
hive客戶端
Hive調優
基於mapreduce優化
合理設置map數
合理設置reduce數
hive架構層優化
不執行mapreduce
本地執行mapreduce
JVM重用
並行化
hiveQL層優化
利用分區表優化
利用桶表優化
join優化
大數據組件來源
大數據來源於哪裏呢?答案是:開源社區(Apache Software Foundation)
我以前聽過一句話:開源社區就像搭積木同樣,一個組件就像一起積木,來源不限,變化不斷。非開源軟件就像建教堂,一旦建成架構長久不變,作的是修修補補。
舉個例子體會一下這句話,在大數據的社區裏邊,幾乎每一年都會有新的頂級項目孵化,從hadoop到spark,再從spark到flink,無窮無止。多個組件組合在一塊兒兒就是一個技術棧,如flume+kafka+storm就構成了流計算三件套,如hdfs+hive+hbase+kylin構成大數據BI技術棧,再如hdfs+hive+spark構成大數據分析的技術棧等等,模塊之間爲所欲爲組合,還有各類替換方案,感受不爽還能二次開發,作的是三個臭皮匠頂一個諸葛亮,追的是廉價普世。非開源的軟件就不同了,如oracle設計出來之後可能十年二十年都不會有大的變化,作的是教堂,追的是精益求精。
沒收住,一會兒說多了,言歸正傳介紹一下大數據關鍵組件的一些來源,再多說一句,在學習大數據的時候,必定要先粗後細,先總體把控各組件所處的位置,如何搭配使用,再具體深刻的瞭解,表1梳理了大數據關鍵組件的來源。
表1 大數據組件來源
名稱 | 來源 | 做用 |
---|---|---|
HDFS | Google的GFS開源實現 | 分佈式文件存儲 |
mapreduce | Google的mapreduce開源實現 | 離線計算框架(筆者已經不多用了) |
HBase | Google的BigTable的開源實現 | key-value列式數據庫 |
Zookeeper | Google的Chubby的開源實現 | 分佈式協做 |
hive | facebook團隊開發 | 大數據倉庫 |
Spark | 加州大學伯克利分校AMP實驗室 | 基於內存的計算框架(第三代引擎) |
Flink | 德國柏林工業大學開源 | 第四代大數據引擎(被阿里極力推廣吹捧) |
Storm | Twitter將其開源 | 流計算引擎 |
Yarn | Apache孵化 | 分佈式資源調度(筆者戲稱hadoop起飛的翅膀) |
在表1中有一個點是筆者比較關注的,那就是spark與flink之爭,二者都能兼顧流批計算,但出發點卻相反,spark以批代流,流是塊裝批;flink以流代替批,批是有界流。中間的些許故事,後續聽筆者慢慢道來,擋!(一聲清脆醒木聲,響起)
Hive簡介
定義
Facebook爲了解決海量日誌數據的分析而開發了hive,後來開源給了Apache基金會組織。 hive是一種用SQL語句來協助讀寫、管理存儲在HDFS上的大數據集的數據倉庫軟件。
hive特色
▪ hive 最大的特色是經過類 SQL 來分析大數據,而避免了寫 mapreduce Java 程序來分析數據,這樣使得分析數據更容易。
▪數據是存儲在HDFS上的,hive自己並不提供數據的存儲功能
▪hive是將數據映射成數據庫和一張張的表,庫和表的元數據信息通常存在關係型數據庫上(好比MySQL)。
▪數據存儲方面:他可以存儲很大的數據集,而且對數據完整性、格式要求並不嚴格。
▪數據處理方面:不適用於實時計算和響應,使用於離線分析。
hive基本語法
hive中的語句有點相似於mysql語句,主要分爲DDL,DML,DQL,在此筆者就不作詳細介紹了,略微指出一點hive表分爲內部表、外部表、分區表和分桶表,感興趣的讀者能夠查閱相關資料。
Hive原理
hive架構圖
hive內核
hive 的內核是驅動引擎,驅動引擎由四部分組成,這四部分分別是:
▪解釋器:解釋器的做用是將hiveSQL語句轉換爲語法樹(AST)。
▪編譯器:編譯器是將語法樹編譯爲邏輯執行計劃。
▪優化器:優化器是對邏輯執行計劃進行優化。
▪執行器:執行器是調用底層的運行框架執行邏輯執行計劃。
hive底層存儲
hive的數據是存儲在HDFS上,hive中的庫和表能夠看作是對HDFS上數據作的一個映射,因此hive必須運行在一個hadoop集羣上。
hive程序執行過程
hive執行器是將最終要執行的mapreduce程序放到YARN上以一系列job的方式去執行。
hive元數據存儲
hive的元數據是通常是存儲在MySQL這種關係型數據庫上的,hive與MySQL之間經過 MetaStore服務交互。
表2 hive元數據相關信息
Owner | 庫、表的全部者 | CreateTime | 建立時間 |
---|---|---|---|
LastAccessTime | 最近修改時間 | Location | 存儲位置 |
Table Type | 表類型(內部表、外部表) | Table Field | 表的字段信息 |
hive客戶端
hive有不少種客戶端,下邊簡單列舉了幾個:
▪ cli命令行客戶端:採用交互窗口,用hive命令行和hive進行通訊。
▪ hiveServer2客戶端:用Thrift協議進行通訊,Thrift是不一樣語言之間的轉換器,是鏈接不一樣語言程序間的協議,經過JDBC或者ODBC去訪問hive(這個是目前hive官網推薦使用的鏈接方式)。
▪ HWI客戶端:hive自帶的客戶端,可是比較粗糙,通常不用。
▪ HUE客戶端:經過Web頁面來和hive進行交互,使用比較,通常在CDH中進行集成。
Hive調優
hadoop就像吞吐量巨大的輪船,啓動開銷大,若是每次只作小數量的輸入輸出,利用率將會很低。因此用好hadoop的首要任務是增大每次任務所搭載的數據量。hive優化時,把hive Sql當作mapreduce 程序來讀,而不是當作SQL來讀。hive優化這要從三個層面進行,分別是基於mapreduce優化、hive架構層優化和hiveQL層優化。
基於mapreduce優化
合理設置map數
上面的mapreduce執行過程部分介紹了,在執行map函數以前會先將HDFS上文件進行分片,獲得的分片作爲map函數的輸入,因此map數量取決於map的輸入分片(inputsplit),一個輸入分片對應於一個map task,輸入分片由三個參數決定,如表3:
表3 輸入分片決定參數
參數名 | 默認值 | 備註 |
---|---|---|
dfs.block.size | 128M | HDFS上數據塊的大小 |
mapreduce.min.split.size | 0 | 最小分片數 |
mapreduce.max.split.size | 256M | 最大分片數 |
公式:分片大小=max(mapreduce.min.split.size,min(dfs.block.size, mapreduce.max.split.size)),默認狀況下分片大小和dfs.block.size是一致的,即一個HDFS數據塊對應一個輸入分片,對應一個map task。這時候一個map task中只處理一臺機器上的一個數據塊,不須要將數據跨網絡傳輸,提升了數據處理速度。
合理設置reduce數
決定 reduce 數量的相關參數如表4:
表4 reduce數決定參數
參數名 | 默認值 | 備註 |
---|---|---|
hive.exec.reducers.bytes.per.reducer | 1G | 一個reduce數據量的大小 |
hive.exec.reducers.max | 999 | hive 最大的個數 |
mapred.reduce.tasks | -1 | reduce task 的個數,-1 是根據hive.exec.reducers.bytes.per.reducer 自動調整 |
因此能夠用set mapred.reduce.tasks手動調整reduce task個數。
hive架構層優化
不執行mapreduce
hive從HDFS讀取數據,有兩種方式:啓用mapreduce讀取、直接抓取。
set hive.fetch.task.conversion=more
hive.fetch.task.conversion參數設置成more,能夠在 select、where 、limit 時啓用直接抓取方式,能明顯提高查詢速度。
本地執行mapreduce
hive在集羣上查詢時,默認是在集羣上N臺機器上運行,須要多個機器進行協調運行,這個方式很好地解決了大數據量的查詢問題。可是當hive查詢處理的數據量比較小時,其實沒有必要啓動分佈式模式去執行,由於以分佈式方式執行就涉及到跨網絡傳輸、多節點協調等,而且消耗資源。這個時間能夠只使用本地模式來執行mapreduce job,只在一臺機器上執行,速度會很快。
JVM重用
由於hive語句最終要轉換爲一系列的mapreduce job的,而每個mapreduce job是由一系列的map task和Reduce task組成的,默認狀況下,mapreduce中一個map task或者一個Reduce task就會啓動一個JVM進程,一個task執行完畢後,JVM進程就退出。這樣若是任務花費時間很短,又要屢次啓動JVM的狀況下,JVM的啓動時間會變成一個比較大的消耗,這個時候,就能夠經過重用JVM來解決。
set mapred.job.reuse.jvm.num.tasks=5
這個設置就是制定一個jvm進程在運行屢次任務以後再退出,這樣一來,節約了不少的 JVM的啓動時間。
並行化
一個hive sql語句可能會轉爲多個mapreduce job,每個job就是一個stage,這些 job 順序執行,這個在hue的運行日誌中也能夠看到。可是有時候這些任務之間並非是相互依賴的,若是集羣資源容許的話,可讓多個並不相互依賴stage併發執行,這樣就節約了時間,提升了執行速度,可是若是集羣資源匱乏時,啓用並行化反卻是會致使各個job相互搶佔資源而致使總體執行性能的降低。
啓用並行化:
set hive.exec.parallel=true
hiveQL層優化
利用分區表優化
分區表是在某一個或者某幾個維度上對數據進行分類存儲,一個分區對應於一個目錄。在這中的存儲方式,當查詢時,若是篩選條件裏有分區字段,那麼hive只須要遍歷對應分區目錄下的文件便可,不用全局遍歷數據,使得處理的數據量大大減小,提升查詢效率。
當一個hive表的查詢大多數狀況下,會根據某一個字段進行篩選時,那麼很是適合建立爲分區表。
利用桶表優化
桶表的概念在本教程第一步有詳細介紹,就是指定桶的個數後,存儲數據時,根據某一個字段進行哈希後,肯定存儲再哪一個桶裏,這樣作的目的和分區表相似,也是使得篩選時不用全局遍歷全部的數據,只須要遍歷所在桶就能夠了。
hive.optimize.bucketmapJOIN=true;
hive.input.format=org.apache.hadoop.hive.ql.io.bucketizedhiveInputFormat;
hive.optimize.bucketmapjoin=true;
hive.optimize.bucketmapjoin.sortedmerge=true;
join優化
▪ 優先過濾後再join,最大限度地減小參與join的數據量。
▪ 小表join大表原則
應該遵照小表join大表原則,緣由是join操做的reduce階段,位於join左邊的表內容會被加載進內存,將條目少的表放在左邊,能夠有效減小發生內存溢出的概率。join中執行順序是從作到右生成job,應該保證連續查詢中的表的大小從左到右是依次增長的。
▪ join on條件相同的放入一個job
hive中,當多個表進行join時,若是join on的條件相同,那麼他們會合併爲一個
mapreduce job,因此利用這個特性,能夠將相同的join on的放入一個job來節省執行時間。
select pt.page_id,count(t.url) PV
from rpt_page_type pt join ( select url_page_id,url from trackinfo where ds='2016-10-11' ) t on pt.page_id=t.url_page_id join ( select page_id from rpt_page_kpi_new where ds='2016-10-11' ) r on t.url_page_id=r.page_id group by pt.page_id;
▪ 啓用mapjoin
mapjoin是將join雙方比較小的表直接分發到各個map進程的內存中,在map進程中進行join操做,這樣就省掉了reduce步驟,提升了速度。
▪ 桶表mapjoin
當兩個分桶表join時,若是join on的是分桶字段,小表的分桶數時大表的倍數時,能夠啓用map join來提升效率。啓用桶表mapjoin要啓用hive.optimize.bucketmapjoin參數。
▪ Group By數據傾斜優化
Group By很容易致使數據傾斜問題,由於實際業務中,一般是數據集中在某些點上,這也符合常見的2/8原則,這樣會形成對數據分組後,某一些分組上數據量很是大,而其餘的分組上數據量很小,而在mapreduce程序中,同一個分組的數據會分配到同一個reduce操做上去,致使某一些reduce壓力很大,其餘的reduce壓力很小,這就是數據傾斜,整個job 執行時間取決於那個執行最慢的那個reduce。
解決這個問題的方法是配置一個參數:set hive.groupby.skewindata=true。
當選項設定爲true,生成的查詢計劃會有兩個MR job。第一個MR job 中,map的輸出結果會隨機分佈到Reduce中,每一個Reduce作部分聚合操做,並輸出結果,這樣處理的結果是相同的Group By Key有可能被分發到不一樣的Reduce中,從而達到負載均衡的目的;第二個MR job再根據預處理的數據結果按照Group By Key分佈到Reduce中(這個過程能夠保證相同的GroupBy Key被分佈到同一個Reduce中),最後完成最終的聚合操做。
▪ Order By 優化
由於order by只能是在一個reduce進程中進行的,因此若是對一個大數據集進行order by,會致使一個reduce進程中處理的數據至關大,形成查詢執行超級緩慢。
▪ 一次讀取屢次插入
▪ Join字段顯示類型轉換
▪ 使用orc、parquet等列式存儲格式
閱讀本文的人還看了:
深度學習(Deep Learning)資料大全(不斷更新)
用TensorFlow教你作手寫字識別(準確率94.09%)
掃碼關注.大數據技術宅
你點的每一次好看,我都認真當成了喜歡