Hive知識點

hive介紹

Hive通常意義上來說徘层,是把一個SQL轉(zhuǎn)化成一個分布式作業(yè),如MapReduce吻商,Spark或者Tez掏颊。無論Hive的底層執(zhí)行框架是MapReduce、Spark還是Tez艾帐,其原理基本都類似乌叶。

而目前,由于MapReduce穩(wěn)定柒爸,容錯性好准浴,大量數(shù)據(jù)情況下使用磁盤,能處理的數(shù)據(jù)量大捎稚,所以目前Hive的主流執(zhí)行框架是MapReduce乐横,但性能相比Spark和Tez也就較低。

Hive的基本組成

  1. 用戶接口:包括 CLI今野、JDBC/ODBC葡公、WebGUI。
    CLI:command line interface条霜,命令行接口催什。
    Hive WEB Interface(HWI):hive客戶端提供了一種通過網(wǎng)頁的方式訪問hive所提供的服務(wù)。
    ThriftServers:提供JDBC和ODBC接入的能力,它用來進行可擴展且跨語言的服務(wù)的開發(fā)宰睡,hive集成了該服務(wù)蒲凶,能讓不同的編程語言調(diào)用hive的接口气筋。

  2. 元數(shù)據(jù)存儲:通常是存儲在關(guān)系數(shù)據(jù)庫如 mysql , derby中。

  3. 語句轉(zhuǎn)換:解釋器旋圆、編譯器宠默、優(yōu)化器、執(zhí)行器灵巧。

    基本組成

  4. 查詢語言搀矫。由于 SQL 被廣泛的應(yīng)用在數(shù)據(jù)倉庫中,因此孩等,專門針對 Hive 的特性設(shè)計了類 SQL 的查詢語言 HQL艾君。熟悉 SQL 開發(fā)的開發(fā)者可以很方便的使用 Hive 進行開發(fā)采够。

  5. 數(shù)據(jù)存儲位置肄方。Hive 是建立在Hadoop 之上的,所有 Hive 的數(shù)據(jù)都是存儲在HDFS 中的蹬癌。

  6. 數(shù)據(jù)格式权她。Hive 中沒有定義專門的數(shù)據(jù)格式,數(shù)據(jù)格式可以由用戶指定逝薪,用戶定義數(shù)據(jù)格式需要指定三個屬性:列分隔符(通常為空格隅要、”\t”、”\x001″)董济、行分隔符(”\n”)以及讀取文件數(shù)據(jù)的方法(Hive 中默認有三個文件格式 TextFile步清,SequenceFile 以及 RCFile)。由于在加載數(shù)據(jù)的過程中虏肾,不需要從用戶數(shù)據(jù)格式到 Hive 定義的數(shù)據(jù)格式的轉(zhuǎn)換廓啊,因此,Hive 在加載的過程中不會對數(shù)據(jù)本身進行任何修改封豪,而只是將數(shù)據(jù)內(nèi)容復(fù)制或者移動到相應(yīng)的 HDFS 目錄中谴轮。

  7. 數(shù)據(jù)更新。由于 Hive 是針對數(shù)據(jù)倉庫應(yīng)用設(shè)計的吹埠,而數(shù)據(jù)倉庫的內(nèi)容是讀多寫少的第步。因此,Hive 中不支持對數(shù)據(jù)的改寫和添加缘琅,所有的數(shù)據(jù)都是在加載的時候中確定好的粘都。

  8. 索引。之前已經(jīng)說過刷袍,Hive 在加載數(shù)據(jù)的過程中不會對數(shù)據(jù)進行任何處理驯杜,甚至不會對數(shù)據(jù)進行掃描,因此也沒有對數(shù)據(jù)中的某些 Key 建立索引做个。Hive 要訪問數(shù)據(jù)中滿足條件的特定值時鸽心,需要暴力掃描整個數(shù)據(jù)滚局,因此訪問延遲較高。由于 MapReduce 的引入顽频, Hive 可以并行訪問數(shù)據(jù)藤肢,因此即使沒有索引,對于大數(shù)據(jù)量的訪問糯景,Hive 仍然可以體現(xiàn)出優(yōu)勢嘁圈。

hive的四種表類型

  1. 內(nèi)部表(受控表),就是一般的表蟀淮,前面講到的表都是內(nèi)部表最住,當表定義被刪除的時候,表中的數(shù)據(jù)隨之一并被刪除怠惶。
  2. 外部表涨缚,數(shù)據(jù)存在與否和表的定義互不約束,僅僅只是表對hdfs上相應(yīng)文件的一個引用策治,當刪除表定義的時候脓魏,表中的數(shù)據(jù)依然存在。

創(chuàng)建外部表通惫,external是外部表的關(guān)鍵字茂翔,也是和內(nèi)部表有區(qū)別的地方
create external table tblName(colName colType...);
加載數(shù)據(jù)
alter table tblName set location 'hdfs_absolute_uri';

外部表還可以在創(chuàng)建表的時候指定數(shù)據(jù)的位置,引用當前位置的數(shù)據(jù)履腋。
create external table tblName(colName colType...) location 'hdfs_absolute_uri';

內(nèi)部表和外部表的轉(zhuǎn)換:
內(nèi)——>外
alter table tblName set tblproperties('EXTERNAL'='TRUE');
外——>內(nèi)
alter table tblName set tblproperties('EXTERNAL'='FALSE');

  1. 分區(qū)表珊燎,表對應(yīng)一個目錄,分區(qū)也對應(yīng)一個目錄遵湖,分區(qū)中的數(shù)據(jù)對應(yīng)文件悔政。
    如何創(chuàng)建一張分區(qū)表?只需要在之前的創(chuàng)建表后面使用partition by加上分區(qū)字段就可以了奄侠,eg.
create table tblName (
   id int comment 'ID',
   name string comment 'name' 
  ) partitioned by (dt date comment 'create time')
row format delimited
fields terminated by '\t';

向分區(qū)表中插入數(shù)據(jù)(要指定分區(qū))
load data local inpath linux_fs_path into table tblName partition(dt='2015-12-12');

多個分區(qū)如何創(chuàng)建卓箫?
和單分區(qū)表的創(chuàng)建類似:

create table tblName (
   id int comment 'ID',
   name string comment 'name' 
  ) partitioned by (year int comment 'admission year', school string comment 'school name')
  row format delimited
  fields terminated by '\t';

同時也可以從hdfs上引用數(shù)據(jù):
alter table tblName partition(year='2015', school='crxy') set 'hdfs_absolute_uri';
注意:
必須得現(xiàn)有分區(qū),必須要使用hdfs絕對路徑。

  1. 桶表
    表對應(yīng)目錄垄潮,桶對應(yīng)文件烹卒,桶表是對存入的數(shù)據(jù)按照某個字段進行哈希取值,值相同的放到同一個文件存儲弯洗。對于每一個表或者是分區(qū)旅急,Hive可以進一步組織成桶,也就是說桶是更為細粒度的數(shù)據(jù)范圍劃分牡整。Hive是針對某一列進行分桶藐吮。Hive采用對列值哈希,然后除以桶的個數(shù)求余的方式?jīng)Q定該條記錄存放在哪個桶中。分桶的好處是可以獲得更高的查詢處理效率谣辞。使取樣更高效迫摔。

創(chuàng)建 emp_bucket 表,字段如下泥从,按照 job 字段分成四個桶

create table bucketed_user(
  id int,
  name string
)
clustered by(id) sorted by(name) into 4 buckets
row format delimited fields terminated by '\t'
stored as textfile;

我們使用用戶id來確定如何劃分桶(Hive使用對值進行哈希并將結(jié)果除于桶的個數(shù)取余數(shù)的方式進行分桶)

如何加載數(shù)據(jù)句占?不能使用load data這種方式,需要從別的表來引用
insert into bucketed_user select * from user;
注意:在插入數(shù)據(jù)之前需要先設(shè)置開啟桶操作躯嫉,不然插入數(shù)據(jù)不會設(shè)置為桶!

set hive.enforce.bucketing=true;

當從桶表中進行查詢時纱烘,hive會根據(jù)分桶的字段進行計算分析出數(shù)據(jù)存放的桶中,然后直接到對應(yīng)的桶中去取數(shù)據(jù)祈餐,這樣做就很好的提高了效率擂啥。

Hive 表默認的倉庫路徑:user/hive/warehouse/tablename

Group By和Join

首先是Group By

例如我們有一條SQL語句:

INSERT INTO TABLE pageid_age_sum 
SELECT pageid, age, count(1) 
FROM pv_users 
GROUP BY pageid, age;

把每個網(wǎng)頁的閱讀數(shù)按年齡進行分組統(tǒng)計。由于前面介紹了帆阳,MapReduce就是一個Group By的過程哺壶,這個SQL翻譯成MapReduce就是相對簡單的。

我們在Map端舱痘,每一個Map讀取一部分表的數(shù)據(jù)变骡,通常是64M或者128M离赫,然后按需要Group By的Key分發(fā)到Reduce端芭逝。經(jīng)過Shuffle Sort,每一個Key再在Reduce端進行聚合(這里是Count)渊胸,然后就輸出了最終的結(jié)果旬盯。值得一提的是,Distinct在實現(xiàn)原理上與Group By類似翎猛。當Group By遇上 Distinct……例如:

SELECT pageid, COUNT(DISTINCT userid) FROM page_view GROUP BY pageid

Hive 實現(xiàn)成MapReduce的原理如下:

也就是說Map分發(fā)到Reduce的時候胖翰,會使用pageid和userid作為聯(lián)合分發(fā)鍵,再去聚合(Count)切厘,輸出結(jié)果萨咳。

介紹了這么多原理,重點還是為了使用疫稿,為了適應(yīng)場景和業(yè)務(wù)培他,為了優(yōu)化。從原理上可以看出遗座,當遇到Group By的查詢時舀凛,會按Group By 鍵進行分發(fā)?如果鍵很多途蒋,撐爆了機器會怎么樣猛遍?

對于Impala,或Spark,為了快懊烤,key在內(nèi)存中梯醒,爆是經(jīng)常的。爆了就失敗了腌紧。對于Hive冤馏,Key在硬盤,本身就比Impala, Spark的處理能力大上幾萬倍寄啼。但……不幸的是逮光,硬盤也有可能爆。

當然墩划,硬盤速度也比內(nèi)存慢上不少涕刚,這也是Hive總是被吐槽的原因,場景不同乙帮,要明白自己使用的場景杜漠。當Group By Key大到連硬盤都能撐爆時……這個時候可能就需要優(yōu)化了。

Group By優(yōu)化通常有Map端數(shù)據(jù)聚合和傾斜數(shù)據(jù)分發(fā)兩種方式察净。Map端部分聚合驾茴,配置開關(guān)是hive.map.aggr

也就是執(zhí)行SQL前先執(zhí)行 set hive.map.aggr=true;它的原理是Map端在發(fā)到Reduce端之前先部分聚合一下。來減少數(shù)據(jù)量氢卡。因為我們剛才已經(jīng)知道锈至,聚合操作是在Reduce端完成的,只要能有效的減少Reduce端收到的數(shù)據(jù)量译秦,就能有效的優(yōu)化聚合速度峡捡,避免爆機,快速拿到結(jié)果筑悴。

另外一種方式則是針對傾斜的key做兩道作業(yè)的聚合们拙。什么是傾斜的數(shù)據(jù)?比如某貓雙11交易阁吝,華為賣了1億臺砚婆,蘋果賣了10萬臺。華為就是典型的傾斜數(shù)據(jù)了突勇。如果要統(tǒng)計華為和蘋果装盯,會用兩個Reduce作Group By,一個處理1億臺与境,一個處理10萬臺验夯,那個1億臺的就是傾余。

由于按key分發(fā)摔刁,遇到傾斜數(shù)據(jù)怎么辦挥转?

可以使用hive.groupby.skewindata選項,通過兩道MapReduce作業(yè)來處理。當選項設(shè)定為 true绑谣,生成的查詢計劃會有兩個 MR Job党窜。第一個 MR Job 中,Map 的輸出結(jié)果集合會隨機分布到Reduce 中借宵,每個 Reduce 做部分聚合操作幌衣,并輸出結(jié)果,這樣處理的結(jié)果是相同的 Group By Key有可能被分發(fā)到不同的 Reduce 中壤玫,從而達到負載均衡的目的豁护;第二個 MR Job 再根據(jù)預(yù)處理的數(shù)據(jù)結(jié)果按照 Group ByKey 分布到 Reduce 中(這個過程可以保證相同的 Group By Key 被分布到同一個 Reduce中),最后完成最終的聚合操作欲间。

第一道作業(yè):Map隨機分發(fā)楚里,按gby key部分聚合
第二道作業(yè):第一道作業(yè)結(jié)果Map傾斜的key分發(fā),按gbk key進行最終聚合

無論你使用Map端猎贴,或者兩道作業(yè)班缎。其原理都是通過部分聚合來來減少數(shù)據(jù)量。能不能部分聚合她渴,部分聚合能不能有效減少數(shù)據(jù)量达址,通常與UDAF,也就是聚合函數(shù)有關(guān)趁耗。也就是只對代數(shù)聚合函數(shù)有效沉唠,對整體聚合函數(shù)無效。

所謂代數(shù)聚合函數(shù)对粪,就是由部分結(jié)果可以匯總出整體結(jié)果的函數(shù)右冻,如count装蓬,sum著拭。 所謂整體聚合函數(shù),就是無法由部分結(jié)果匯總出整體結(jié)果的函數(shù)牍帚,如avg儡遮,mean。 比如暗赶,sum, count鄙币,知道部分結(jié)果可以加和得到最終結(jié)果。 而對于蹂随,mean十嘿,avg,知道部分數(shù)據(jù)的中位數(shù)或者平均數(shù)岳锁,是求不出整體數(shù)據(jù)的中位數(shù)和平均數(shù)的绩衷。

在遇到復(fù)雜邏輯的時候,還是要具體問題具體分析,根據(jù)系統(tǒng)的原理咳燕,優(yōu)化邏輯勿决。剛才說了,Hive最重要的是Group By和Join招盲,所以下面我們講Join.

JOIN
例如這樣一個查詢:

INSERT INTO TABLE pv_users 
SELECT pv.pageid, u.age 
FROM page_view pv JOIN user u ON (pv.userid = u.userid);
image

把訪問和用戶表進行關(guān)聯(lián)低缩,生成訪問用戶表。Hive的Join也是通過MapReduce來完成的曹货。

image

就上面的查詢咆繁,在MapReduce的Join的實現(xiàn)過程如下:

image

Map端會分別讀入各個表的一部分數(shù)據(jù),把這部分數(shù)據(jù)進行打標顶籽,例如pv表標1么介,user表標2.

Map讀取是分布式進行的。標完完后分發(fā)到Reduce端蜕衡,Reduce 端根據(jù)Join Key壤短,也就是關(guān)聯(lián)鍵進行分組。然后按打的標進行排序慨仿,也就是圖上的Shuffle Sort久脯。

在每一個Reduce分組中,Key為111的在一起镰吆,也就是一臺機器上帘撰。同時,pv表的數(shù)據(jù)在這臺機器的上端万皿,user表的數(shù)據(jù)在這臺機器的下端摧找。

這時候,Reduce把pv表的數(shù)據(jù)讀入到內(nèi)存里牢硅,然后逐條與硬盤上user表的數(shù)據(jù)做Join就可以了蹬耘。

從這個實現(xiàn)可以看出,我們在寫Hive Join的時候减余,應(yīng)該盡可能把小表(分布均勻的表)寫在左邊综苔,大表(或傾斜表)寫在右邊。這樣可以有效利用內(nèi)存和硬盤的關(guān)系位岔,增強Hive的處理能力如筛。

同時由于使用Join Key進行分發(fā), Hive也只支持等值Join抒抬,不支持非等值Join杨刨。由于Join和Group By一樣存在分發(fā),所以也同樣存在著傾斜的問題擦剑。所以Join也要對抗傾斜數(shù)據(jù)妖胀,提升查詢執(zhí)行性能可免。

通常,有一種執(zhí)行非匙鲈粒快的Join叫Map Join 浇借。

Map Join 優(yōu)化

手動的Map Join SQL如下:

INSERT INTO TABLE pv_users 
SELECT /*+ MAPJOIN(pv) */ pv.pageid, u.age 
FROM page_view pv JOIN user u 
ON (pv.userid = u.userid);

還是剛才的例子,用Map Join執(zhí)行

Map Join通常只適用于一個大表和一個小表做關(guān)聯(lián)的場景怕品,例如事實表和維表的關(guān)聯(lián)妇垢。

原理如上圖,用戶可以手動指定哪個表是小表肉康,然后在客戶端把小表打成一個哈希表序列化文件的壓縮包闯估,通過分布式緩存均勻分發(fā)到作業(yè)執(zhí)行的每一個結(jié)點上。然后在結(jié)點上進行解壓吼和,在內(nèi)存中完成關(guān)聯(lián)涨薪。

Map Join全過程不會使用Reduce,非常均勻炫乓,不會存在數(shù)據(jù)傾斜問題刚夺。默認情況下,小表不應(yīng)該超過25M末捣。在實際使用過程中侠姑,手動判斷是不是應(yīng)該用Map Join太麻煩了,而且小表可能來自于子查詢的結(jié)果箩做。

Hive有一種稍微復(fù)雜一點的機制莽红,叫Auto Map Join

還記得原理中提到的物理優(yōu)化器?Physical Optimizer么邦邦?它的其中一個功能就是把Join優(yōu)化成Auto Map Join

圖上左邊是優(yōu)化前的安吁,右邊是優(yōu)化后的

優(yōu)化過程是把Join作業(yè)前面加上一個條件選擇器ConditionalTask和一個分支。左邊的分支是MapJoin燃辖,右邊的分支是Common Join(Reduce Join)

看看左邊的分支是不是和我們上上一張圖很像鬼店?

這個時候,我們在執(zhí)行的時候郭赐,就由這個Conditional Task 進行實時路徑選擇薪韩,遇到小于25兆走左邊,大于25兆走右邊捌锭。

在比較新版的Hive中,Auto Mapjoin是默認開啟的罗捎。如果沒有開啟观谦,可以使用一個開關(guān), set hive.auto.convert.join=true 開啟桨菜。
當然豁状,Join也會遇到和上面的Group By一樣的傾斜問題捉偏。

Hive 也可以通過像Group By一樣兩道作業(yè)的模式單獨處理一行或者多行傾斜的數(shù)據(jù)。

hive 中設(shè)定

set hive.optimize.skewjoin = true; 
set hive.skewjoin.key = skew_key_threshold (default = 100000)

其原理是就在Reduce Join過程泻红,把超過十萬條的傾斜鍵的行寫到文件里夭禽,回頭再起一道Join單行的Map Join作業(yè)來單獨收拾它們。最后把結(jié)果取并集就是了谊路。如上圖所示讹躯。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市缠劝,隨后出現(xiàn)的幾起案子潮梯,更是在濱河造成了極大的恐慌,老刑警劉巖惨恭,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秉馏,死亡現(xiàn)場離奇詭異,居然都是意外死亡脱羡,警方通過查閱死者的電腦和手機萝究,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锉罐,“玉大人糊肤,你說我怎么就攤上這事∶ケ桑” “怎么了馆揉?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長抖拦。 經(jīng)常有香客問我升酣,道長,這世上最難降的妖魔是什么态罪? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任噩茄,我火速辦了婚禮,結(jié)果婚禮上复颈,老公的妹妹穿的比我還像新娘绩聘。我一直安慰自己,他們只是感情好耗啦,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布凿菩。 她就那樣靜靜地躺著,像睡著了一般帜讲。 火紅的嫁衣襯著肌膚如雪衅谷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天似将,我揣著相機與錄音获黔,去河邊找鬼蚀苛。 笑死,一個胖子當著我的面吹牛玷氏,可吹牛的內(nèi)容都是我干的堵未。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼盏触,長吁一口氣:“原來是場噩夢啊……” “哼渗蟹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起耻陕,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤拙徽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后诗宣,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體膘怕,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年召庞,在試婚紗的時候發(fā)現(xiàn)自己被綠了岛心。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡篮灼,死狀恐怖忘古,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情诅诱,我是刑警寧澤髓堪,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站娘荡,受9級特大地震影響干旁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜炮沐,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一争群、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧大年,春花似錦换薄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至遏餐,卻和暖如春伦腐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背失都。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工柏蘑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人粹庞。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓咳焚,卻偏偏與公主長得像,于是被迫代替她去往敵國和親庞溜。 傳聞我的和親對象是個殘疾皇子革半,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361