大數據面試系列之——Hive

Hive是一個數據倉庫基礎工具在Hadoop中用來處理結構化數據

1.Hive與傳統數據庫的區別

  • 1、數據存儲位置:Hive是建立在Hadoop之上的,所有的Hive的數據都是存儲在HDFS中的。而數據庫則可以將數據保存在塊設備或本地文件系統中。
  • 2、數據格式:Hive中沒有定義專門的數據格式,由用戶指定,需要指定三個屬性:列分隔符,行分隔符,以及讀取文件數據的方法。數據庫中,存儲引擎定義了自己的數據格式。所有數據都會按照一定的組織存儲。
  • 3、數據更新:Hive的內容是讀多寫少的,因此,不支持對數據的改寫和刪除,數據都在加載的時候中確定好的。數據庫中的數據通常是需要經常進行修改。
  • 4、執行延遲:Hive在查詢數據的時候,需要掃描整個表(或分區),因此延遲較高,只有在處理大數據是纔有優勢。數據庫在處理小數據是執行延遲較低。
  • 5、索引:Hive沒有,數據庫有
  • 6、執行:Hive是MapReduce,數據庫是Executor
  • 7、可擴展性:Hive高,數據庫低
  • 8、數據規模:Hive大,數據庫小

2.Hive的內部表和外部表的區別
在刪除內部表的時候,Hive將會把屬於表的元數據和數據全部刪掉,而刪除外部表的時候,Hive僅僅刪除外部表的元數據,數據是不會刪除的。

3.Hive的分區表和分桶表的區別

  • 分區:
    Hive的分區使用HDFS的子目錄功能實現。每一個子目錄包含了分區對應的列名和每一列的值
    Hive的分區方式:由於Hive實際是存儲在HDFS上的抽象,Hive的一個分區名對應一個目錄名,子分區名就是子目錄名,並不是一個實際字段。
  • 分桶:
    分桶表是在表或者分區表的基礎上,進一步對錶進行組織,Hive使用 對分桶所用的值;
    進行hash,並用hash結果除以桶的個數做取餘運算的方式來分桶,保證了每個桶中都有數據,但每個桶中的數據條數不一定相等。

主要區別有三:
1.分區表對應的是HDFS上的目錄,分桶表對應的是HDFS上的文件。
2.分桶隨機分割數據庫,分區是非隨機分割數據庫。因爲分桶是按照列的哈希函數進行分割的,相對比較平均;而分區是按照列的值來進行分割的,容易造成數據傾斜。
3.分桶是對應不同的文件(細粒度),分區是對應不同的文件夾(粗粒度);桶是更爲細粒度的數據範圍劃分,分桶的比分區獲得更高的查詢處理效率,使取樣更高效。

4.Hive表的元數據存儲方式
Hive支持三種不同的元存儲服務器,分別爲:內嵌式元存儲服務器、本地元存儲服務器、遠程元存儲服務器,每種存儲方式使用不同的配置參數。

  • 1.內嵌式元存儲主要用於單元測試,在該模式下每次只有一個進程可以連接到元存儲,Derby是內嵌式元存儲的默認數據庫。
  • 2.在本地模式下,每個Hive客戶端都會打開到數據存儲的連接並在該連接上請求SQL查詢。
  • 3.在遠程模式下,所有的Hive客戶端都將打開一個到元數據服務器的連接,該服務器依次查詢元數據,元數據服務器和客戶端之間使用Thrift協議通信。

5.Hive中order by,sort by, distribute by ,cluster by的區別

  • 1.order by : order by會對輸入做全局排序,因此只有一個Reducer(多個Reducer無法保證全局有序),然而只有一個Reducer,會導致當輸入規模較大時,消耗較長的計算時間。
  • 2.sort by : sort by不是全局排序,其在數據進入reducer前完成排序,sort by只會保證每個reducer的輸出有序,並不保證全局有序。sort by的數據只能保證在同一個reduce中的數據可以按指定字段排序。
  • 3.distribute by : distribute by是控制在map端如何拆分數據給reduce端的。hive會根據distribute by後面列,對應reduce的個數進行分發,默認是採用hash算法。sort by爲每個reduce產生一個排序文件。在有些情況下,你需要控制某個特定行應該到哪個reducer,這通常是爲了進行後續的聚集操作。distribute by剛好可以做這件事。因此,distribute by經常和sort by配合使用。
  • 4.cluster by : cluster by除了具有distribute by的功能外還兼具sort by的功能。但是排序只能是倒敘排序,不能指定排序規則爲ASC或者DESC。

6.談談Hive的優化

  • 1.Fetch抓取是指,Hive中對某些情況的查詢可以不必使用MapReduce計算,在hive-default.xml.template文件中hive.fetch.task.conversion默認是more,老版本hive默認是minimal,該屬性修改爲more以後,在全局查找、字段查找、limit查找等都不走mapreduce。
  • 2.大小表join時,小表放在左邊,可以有效避免OOM。
  • 3.MapJoin
    如果不指定MapJoin或者不符合MapJoin的條件,那麼Hive解析器會將Join操作轉換成Common Join,即:在Reduce階段完成join。容易發生數據傾斜。可以用MapJoin把小表全部加載到內存在map端進行join,避免reducer處理
    開啓MapJoin參數設置:
    (1)設置自動選擇Mapjoin
    set hive.auto.convert.join = true; 默認爲true
    (2)大表小表的閥值設置(默認25M以下認爲是小表):
    set hive.mapjoin.smalltable.filesize=25000000;
  • 4.Group by
    默認情況下,Map階段同一Key數據分發給一個reduce,當一個key數據過大時就傾斜了。
    並不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端進行部分聚合,最後在Reduce端得出最終結果。
    開啓Map端聚合參數設置
    (1)是否在Map端進行聚合,默認爲True
    hive.map.aggr = true
    (2)在Map端進行聚合操作的條目數目
    hive.groupby.mapaggr.checkinterval = 100000
    (3)有數據傾斜的時候進行負載均衡(默認是false)
    hive.groupby.skewindata = true
    當選項設定爲 true,生成的查詢計劃會有兩個MR Job。第一個MR Job中,Map的輸出結果會隨機分佈到Reduce中,每個Reduce做部分聚合操作,並輸出結果,這樣處理的結果是相同的Group By Key有可能被分發到不同的Reduce中,從而達到負載均衡的目的;第二個MR Job再根據預處理的數據結果按照Group By Key分佈到Reduce中(這個過程可以保證相同的Group By Key被分佈到同一個Reduce中),最後完成最終的聚合操作。
  • 5.Count(distinct)優化
    數據量小的時候不需要優化處理,但是當數據量特別大的時候,由於COUNT DISTINCT操作需要用一個Reduce Task來完成,這一個Reduce需要處理的數據量太大,就會導致整個Job很難完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替換。
  • 6.行列過濾
    列處理:只取需要的列,儘量不要使用select *
    行處理:當兩個表join時,需要加條件過濾時,將where條件加在on 前面。
  • 7.並行執行
    Hive會將一個查詢轉化成一個或者多個階段。這樣的階段可以是MapReduce階段、抽樣階段、合併階段、limit階段。或者Hive執行過程中可能需要的其他階段。默認情況下,Hive一次只會執行一個階段。不過,某個特定的job可能包含衆多的階段,而這些階段可能並非完全互相依賴的,也就是說有些階段是可以並行執行的,這樣可能使得整個job的執行時間縮短。不過,如果有更多的階段可以並行執行,那麼job可能就越快完成。
    通過設置參數hive.exec.parallel值爲true,就可以開啓併發執行。不過,在共享集羣中,需要注意下,如果job中並行階段增多,那麼集羣利用率就會增加。
set hive.exec.parallel=true;              //打開任務並行執行
set hive.exec.parallel.thread.number=16;  //同一個sql允許最大並行度,默認爲8。
  • 8.嚴格模式
    Hive提供了一個嚴格模式,可以防止用戶執行那些可能意向不到的不好的影響的查詢。
    通過設置屬性hive.mapred.mode值爲默認是非嚴格模式nonstrict 。開啓嚴格模式需要修改hive.mapred.mode值爲strict,開啓嚴格模式可以禁止3種類型的查詢。
    1)對於分區表,除非where語句中含有分區字段過濾條件來限制範圍,否則不允許執行。換句話說,就是用戶不允許掃描所有分區。進行這個限制的原因是,通常分區表都擁有非常大的數據集,而且數據增加迅速。沒有進行分區限制的查詢可能會消耗令人不可接受的巨大資源來處理這個表。
    2)對於使用了order by語句的查詢,要求必須使用limit語句。因爲order by爲了執行排序過程會將所有的結果數據分發到同一個Reducer中進行處理,強制要求用戶增加這個LIMIT語句可以防止Reducer額外執行很長一段時間。
    3)限制笛卡爾積的查詢。對關係型數據庫非常瞭解的用戶可能期望在執行JOIN查詢的時候不使用ON語句而是使用where語句,這樣關係數據庫的執行優化器就可以高效地將WHERE語句轉化成那個ON語句。不幸的是,Hive並不會執行這種優化,因此,如果表足夠大,那麼這個查詢就會出現不可控的情況。
  • 9.SQL優化
1.去除查詢中不需要的column
2.Where條件判斷等在TableScan階段就進行過濾
3.利用Partition信息,只讀取符合條件的Partition
4.Map端join,以大表作驅動,小表載入所有mapper內存中
5.調整Join順序,確保以大表作爲驅動表
6.對於數據分佈不均衡的表Group by時,爲避免數據集中到少數的reducer上,分成兩個map-reduce階段。
第一個階段先用Distinct列進行shuffle,然後在reduce端部分聚合,減小數據規模,
第二個map-reduce階段再按group-by列聚合。
7.在map端用hash進行部分聚合,減小reduce端數據處理規模。
發佈了28 篇原創文章 · 獲贊 9 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章