大數據利器Hive

序言:在大數據領域存在一個現象,那就是組件繁多,粗略估計一下輕鬆超過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等列式存儲格式 

閱讀本文的人還看了:


BP神經網絡

初識TensorFlow

GAN模型生成手寫字

深度學習(Deep Learning)資料大全(不斷更新)

OpenCV+TensorFlow實現自定義手寫圖像識別

用TensorFlow教你作手寫字識別(準確率94.09%)

Storm環境搭建(分佈式集羣)

機器學習——邏輯迴歸

 

 

掃碼關注.大數據技術宅

 

你點的每一次好看,我都認真當成了喜歡

相關文章
相關標籤/搜索