有點標(biāo)題黨了浩峡,但是大部分常用知識點也算是涉及到了,希望對你有幫助
Hive是什么错敢?
概念
- ?? 從概念上講:由Facebook開源的一款基于hadoop的用于統(tǒng)計海量結(jié)構(gòu)化數(shù)據(jù)的一個數(shù)據(jù)倉庫翰灾。
- ??從本質(zhì)上講:將HQL語句轉(zhuǎn)換成MapReduce程序的一個工具。
產(chǎn)生:
- 讓了方便非java開發(fā)人員對hdfs上的數(shù)據(jù)做 MapReduce 操作
架構(gòu)
- 從客戶端編輯 sql 語句提交到服務(wù)端稚茅,通過解釋器纸淮,編譯器,優(yōu)化器生成執(zhí)行計劃亚享,然后提交到 Hadoop 集群運行
其中計劃執(zhí)行的最小單元是一個個 operator咽块,每個operator代表一個操作或者一個MR作業(yè)
Hive的元數(shù)據(jù)依賴于關(guān)系型數(shù)據(jù)庫,其真實數(shù)據(jù)是存在于Hadoop之上的
-
下圖為 Hive 架構(gòu)簡圖虹蒋,其中 Hadoop 展示的是 1.x 版本的糜芳,2.x 以后是提交到 yarn上運行。
image.png
支持的數(shù)據(jù)類型
- 復(fù)雜類型
| array_type
| map_type
| struct_type - 簡單類型
|TINYINT
| SMALLINT
| INT
| BIGINT
| BOOLEAN
| FLOAT
| DOUBLE
| STRING
表的類型
- 外部表:刪除表時魄衅,只會刪除元數(shù)據(jù)信息峭竣,而不對真實數(shù)據(jù)進行修改
- 內(nèi)部表:也叫管理表,刪除表時晃虫,會對元數(shù)據(jù)和真實數(shù)據(jù)一起刪除皆撩。
HIve分區(qū)
- 意義
- 其意義主要在于優(yōu)化查詢,對于分區(qū)表哲银,我們一般都要求使用分區(qū)字段進行過濾扛吞,以加快查詢速度
- 靜態(tài)分區(qū)使用
- 建表是指定分區(qū)(其中分區(qū)在hdfs上表現(xiàn)為文件夾分類管理形式)
create table day_hour_table (id int, content string) partitioned by (dt string, hour string);
- 在已有的表上添加分區(qū)
ALTER TABLE table_name ADD PARTITION (dt='2018-06-02', hour='18')
- 在已有表上刪除某分區(qū)
ALTER TABLE table_name DROP PARTITION (dt='2018-06-02', hour='18')
- 向分區(qū)表中添加數(shù)據(jù):
LOAD DATA INPATH "/testFile" INTO TABLE table_name PARTITION(dt='2018-06-02', hour='18')
- 動態(tài)分區(qū)
- 開啟支持動態(tài)分區(qū)
set hive.exec.dynamic.partition=true;
默認(rèn):false
set hive.exec.dynamic.partition.mode=nostrict;
默認(rèn):strict(至少有一個分區(qū)列是靜態(tài)分區(qū))
- 相關(guān)參數(shù)
set hive.exec.max.dynamic.partitions.pernode;
每一個執(zhí)行mr節(jié)點上,允許創(chuàng)建的動態(tài)分區(qū)的最大數(shù)量(100)
set hive.exec.max.dynamic.partitions;
所有執(zhí)行mr節(jié)點上荆责,允許創(chuàng)建的所有動態(tài)分區(qū)的最大數(shù)量(1000)
set hive.exec.max.created.files;
所有的mr job允許創(chuàng)建的文件的最大數(shù)量(100000)
- 加載數(shù)據(jù)
from table_name1
insert overwrite table table_name2 partition(age, sex)
select id, name, age, sex, address distribute by age, sex;
hive 分桶
分桶表是對列值取哈希值的方式滥比,將不同數(shù)據(jù)放到不同文件中存儲。
對于hive中每一個表做院、分區(qū)都可以進一步進行分桶盲泛。
由列的哈希值除以桶的個數(shù)來決定每條數(shù)據(jù)劃分在哪個桶中濒持。適用場景:
數(shù)據(jù)抽樣( sampling )
SMB Join(sort meger bucket join)
- 開啟支持分桶
set hive.enforce.bucketing=true;
默認(rèn):false;設(shè)置為true之后寺滚,mr運行時會根據(jù)bucket的個數(shù)自動分配reduce task個數(shù)柑营。(用戶也可以通過mapred.reduce.tasks自己設(shè)置reduce任務(wù)個數(shù),但分桶時不推薦使用)
注意:一次作業(yè)產(chǎn)生的桶(文件數(shù)量)和reduce task個數(shù)一致村视。
- 創(chuàng)建分桶表
CREATE TABLE tb_name( id INT, name STRING, age INT)
CLUSTERED BY (age) INTO 4 BUCKETS
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
- 加載數(shù)據(jù):
insert into table tb_name select id, name, age from source_tb_name;
- 抽樣
select id, name, age from tb_name tablesample(bucket 1 out of 2 on age);
一共4個桶官套,抽取2(4/2)個bucket的數(shù)據(jù),抽取第1蚁孔、第3(1+2)個bucket的數(shù)據(jù)
- SMB Join
對于一些大表 join 大表 的場景奶赔,
采用分桶表會有比較好的表現(xiàn)效果,
當(dāng)然這里兩個表都要按照同一個規(guī)則進行分桶勒虾。
Beeline 和 HIveServer2
- beeline 要與 HIveServer2 配合使用
- 服務(wù)端啟動 HIveServer2
- 客戶端可以通過
beeline -u jdbc:hive2://hostname:10000/db_name -n username
進行hive的連接 - HiveServer2的另外一個功能纺阔,就是提供給開發(fā)者一個jdbc的開發(fā)接口,
可以通過hive驅(qū)動修然,像訪問 mysql 一樣訪問 Hive - HiveServer2 相比 Hive MetaServer 是很好的隱藏了客戶端,這一點親手配置過 Hive 的同學(xué)可能比較能夠理解质况,因為 beeline 其實是不需要任何配置的愕宋,連上 hiveserver2 就能用,但是 Hive MetaServer 是需要你自己配置 Hive客戶端的结榄。并且高可用的配置只能基于 HiveServer2
Hive 函數(shù)
- UDTF:一進多出函數(shù)中贝,對于某個數(shù)據(jù)經(jīng)過函數(shù)會產(chǎn)生多條記錄,eg: explode
- UDF:一進一出函數(shù)臼朗,對于一個數(shù)據(jù)經(jīng)過函數(shù)處理邻寿,還是一條數(shù)據(jù) eg: to_date
- UDAF:多進一出函數(shù),多條數(shù)據(jù)經(jīng)過函數(shù)處理會聚合成一條數(shù)據(jù) eg: count
- 這塊內(nèi)容其實挺多的视哑,但是官網(wǎng)都有詳細(xì)的文檔,所以下面只是簡單的給出官網(wǎng)鏈接绣否,偷懶一把!5惨恪蒜撮!嘿嘿
- 自定義 UDF
CREATE FUNCTION [db_name.] function_name AS class_name [USING JAR|FILE|ARCHIVE 'file_uri' [, JAR|FILE|ARCHIVE 'file_uri'] ];
Hive 索引
- 目的:優(yōu)化查詢以及檢索性能
- 創(chuàng)建索引:
create index t1_index on table tb_name1(name)
as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' with deferred rebuild
in table t1_index_table;
as:指定索引器;
in table:指定索引表跪呈,若不指定默認(rèn)生成在default__psn2_t1_index__表中
查詢索引
show index on tb_name1;重建索引(建立索引之后必須重建索引才能生效)
ALTER INDEX t1_index ON tb_name1 REBUILD;刪除索引
DROP INDEX IF EXISTS t1_index ON tb_name1;
5.使用的時候根據(jù)索引條件查詢能加快查詢速度段磨,但是由于索引表也是需要維護的,會帶來額外開銷耗绿。
- 實際上苹支,hive作為數(shù)據(jù)倉庫,其實索引的使用還是比較少的误阻,反正我是沒怎么使用過债蜜。晴埂。。
數(shù)據(jù)傾斜
- 什么時數(shù)據(jù)傾斜策幼?什么導(dǎo)致的數(shù)據(jù)傾斜邑时?
一般來說,在分布式計算系統(tǒng)中特姐,我們期望的每個節(jié)點完成任務(wù)的時間是一致的晶丘,
但是實際生產(chǎn)環(huán)境中,因為種種原因會導(dǎo)致某些節(jié)點處理的數(shù)據(jù)較大唐含,
導(dǎo)致完成任務(wù)時間與其他節(jié)點相差很大浅浮,
以至于整個任務(wù)完成時間過長,這就是我們常說的數(shù)據(jù)傾斜一般來說捷枯,導(dǎo)致數(shù)據(jù)傾斜的原因都是因為數(shù)據(jù)分布的不均勻?qū)е碌模?br> 而 Hive 因為底層是通過 MR 實現(xiàn)的滚秩,
所以數(shù)據(jù)傾斜一般都是發(fā)生在 Reduce 端,
而 Reduce 端處理的數(shù)據(jù)是由我們的 Partition 決定的淮捆,
這就為我們尋找數(shù)據(jù)傾斜的原因提供了一個最基本的思路郁油。
當(dāng)我們使用一些類似于 group by , join
等會產(chǎn)生 shuffle 語法的時候,
默認(rèn)的 partition 方式都是通過 key 來決定的攀痊,
所以一般導(dǎo)致數(shù)據(jù)傾斜的原因都是 key 的分布不均勻桐腌。
-
數(shù)據(jù)傾斜解決方案
- Hive自帶的數(shù)據(jù)傾斜解決方案,主要是針對 group by ;
a. 設(shè)置參數(shù) :
set hive.map.aggr=true
,開啟 map 端的聚合功能苟径,也就是 MR 程序中寫的 combiner- hive.groupby.mapaggr.checkinterval:
map端group by執(zhí)行聚合時處理的多少行數(shù)據(jù)(默認(rèn):100000), - hive.map.aggr.hash.min.reduction:
進行聚合的最小比例(預(yù)先對100000條數(shù)據(jù)做聚合案站,若 (聚合之后的數(shù)據(jù)量)/100000 的值大于該配置設(shè) 置值0.5,則不會聚合) - hive.map.aggr.hash.percentmemory:
map端聚合使用的內(nèi)存的最大值 - hive.map.aggr.hash.force.flush.memory.threshold:
map端做聚合操作是hash表的最大可用內(nèi)容棘街,大于該值則會觸發(fā)flush
b. 設(shè)置
set hive.groupby.skewindata=true
蟆盐,開啟Group By 產(chǎn)生數(shù)據(jù)傾斜優(yōu)化該處理方式是將一次group 操作進行了兩次處理,
首先會對map端輸入的數(shù)據(jù)進行隨機分發(fā)給reduce端遭殉,
因為是隨機的石挂,所以數(shù)據(jù)會均勻分發(fā)給reduce 進行 group ,
然后對第一次group處理的數(shù)據(jù)再進行一次正常的 group操作恩沽,
因為有了第一次的處理誊稚,第二次處理的數(shù)據(jù)將會大大減少
從而使得數(shù)據(jù)傾斜問題不再明顯。
嚴(yán)格來說罗心,這并沒有解決數(shù)據(jù)傾斜問題里伯,
但是卻大大減少了數(shù)據(jù)傾斜帶來的影響- Join 產(chǎn)生的數(shù)據(jù)傾斜
a. Map端進行join:適合小表 join 大表的情況
- 通過修改以下配置啟用自動的mapjoin:
set hive.auto.convert.join = true;
(該參數(shù)為true時,Hive自動對左邊的表統(tǒng)計量渤闷,如果是小表就加入內(nèi)存疾瓮,即對小表使用Map join) - hive.mapjoin.smalltable.filesize;
(大表小表判斷的閾值,如果表的大小小于該值則會被加載到內(nèi)存中運行) - hive.ignore.mapjoin.hint飒箭;
(默認(rèn)值:true狼电;是否忽略mapjoin hint 即HQL 語句中的mapjoin
標(biāo)記) - hive.auto.convert.join.noconditionaltask;
(默認(rèn)值:true蜒灰;將普通的join轉(zhuǎn)化為普通的mapjoin時,是否將多個mapjoin轉(zhuǎn)化為一個mapjoin) - hive.auto.convert.join.noconditionaltask.size;
(將多個mapjoin轉(zhuǎn)化為一個mapjoin時肩碟,其表的最大值)
b. 對于兩張都是大表的情況强窖,
我們可以想辦法將一個大表轉(zhuǎn)化為小表,然后采用 a 方案削祈;
另外我們也可以使用分桶的思想翅溺,來加快join;
我們還可以根據(jù)業(yè)務(wù)髓抑,來避免這類問題咙崎,
比如:找到導(dǎo)致數(shù)據(jù)傾斜的 key 過濾出來額外處理。
很多時候吨拍,這個導(dǎo)致傾斜的 key 可能是一個臟數(shù)據(jù)褪猛,那么直接過濾就好了
其中 數(shù)據(jù)傾斜解決方案 這上面的一些方案也可以參考,
HIve 優(yōu)化
談起優(yōu)化羹饰,上面很大一部分內(nèi)容都有涉及伊滋,這里我們主要談?wù)?HQL 優(yōu)化
- 某些容易導(dǎo)致數(shù)據(jù)傾斜的函數(shù)
count(distinct *)
該用法在MR 的 reduce 階段只有一個 reduce 來處理,當(dāng)數(shù)據(jù)量較大會導(dǎo)致嚴(yán)重的數(shù)據(jù)傾斜队秩。
可以通過
select count(1) from (select distinct(uid) d_uid from t)
來優(yōu)化-
order by key
對于全局排序也有上面類似的問題
為了解決上面的問題新啼,我們需要先了解下hive的幾種排序- order by:全局排序,一般不用刹碾,因為其為了全局有序,
將數(shù)據(jù)放到一個reduce里面處理座柱,效率比較低 - cluster by:全局排序迷帜,建議使用,但是只能是降序色洞,不能指定asc和desc
- sort by:局部排序戏锹,這個局部就是每個 reduce 內(nèi)部,
所以不能保證全局有序火诸,
單個使用意義不大锦针,需要結(jié)合distribute by
一起使用 - distribute by:分區(qū)排序,
在分發(fā)數(shù)據(jù)給 reduce 的時候保證 reduce 是有序的置蜀,
結(jié)合sort by
奈搜,
可以做到全局有序
所以上面這個問題可以通過
select a,b,c from t distribute by a sort by a asc, b desc
來解決 - order by:全局排序,一般不用刹碾,因為其為了全局有序,
- Union All insert
//union all
insert overwrite table t
select a,b,c
from t1
union all
select a,b,c from t2
//普通方式
insert overwrite table t
select a,b,c from t1
insert overwrite table t
select a,b,c from t2
limit
limit 限制,對于hive 很多時候都是需要進行全表統(tǒng)計盯荤,然后顯示 limit 限制的條數(shù)的記錄馋吗,對于執(zhí)行速度并沒有多大的提升,如果我們的需求是可以通過抽樣來看整體情況的秋秤,那么全表掃描無疑是很浪費資源的宏粤,所以hive也是提供了相應(yīng)的優(yōu)化機制脚翘,來允許我們采用抽樣使用 limit
hive.limit.optimize.enable=true --- 開啟對數(shù)據(jù)源進行采樣的功能
hive.limit.row.max.size --- 設(shè)置最小的采樣容量
hive.limit.optimize.limit.file --- 設(shè)置最大的采樣樣本數(shù)
join
上文說了不少join的優(yōu)化,這里補充一點:
多個join 相互關(guān)聯(lián)绍哎,盡可能的使用相同的 key 進行關(guān)聯(lián)来农,
這樣就 Hive 就只會使用一個 Maper 去操作
- 本地執(zhí)行
當(dāng)我們覺得有些任務(wù)是殺雞用牛到的時候,
可以嘗試運用本地運行崇堰,
分布式計算只有再數(shù)據(jù)量足夠大的時候才能體現(xiàn)其優(yōu)勢沃于,
否則單機是更快的。
通過mapred.job.tracker=true
參數(shù)開啟本地模式
當(dāng)然揽涮,hive 也提供了自動開啟本地模式的優(yōu)化機制
通過hive.exec.mode.local.auto
開啟自動執(zhí)行饿肺,自動開啟的條件如下:
1.job的輸入數(shù)據(jù)量小于參數(shù):hive.exec.mode.local.auto.inputbytes.max(默認(rèn)128MB)
2.job的map數(shù)必須小于參數(shù):hive.exec.mode.local.auto.tasks.max(默認(rèn)4)
3.job的reduce數(shù)必須為0或者1 - stage 并行執(zhí)行
對于一些復(fù)雜的 hql 可能會需要多個 stage 一起執(zhí)行來完成,默認(rèn)情況下敬辣,hive 是根據(jù)其解析的計劃串行執(zhí)行一個個 stage 的雪标,為了提高執(zhí)行速度,我們可以開啟 stage 并行執(zhí)行溉跃。
通過hive.exec.parallel=true
開啟
stage 是什么? hive 將sql 解析后自動生成的一個抽象概念嵌牺,比如我們要做飯,那么這個 stage 就可以理解為:1.買菜買米龄糊,2.煮飯逆粹,3.炒菜,4.上桌僻弹。如果開啟了并行執(zhí)行那么他嚷,煮飯 和 炒菜 就可以一起執(zhí)行了蹋绽,當(dāng)然前提是你要忙的過來筋蓖,所以集群資源要足夠才行,如果沒開啟鹊奖,那么就傻傻的 先煮飯涂炎,飯熟了设哗,再炒菜
- JVM 重用
這里JVM 重用是針對 hive 底層的執(zhí)行引擎 MR 來說的两蟀,默認(rèn)的一個 task 啟動一個 jvm 進程來執(zhí)行。
通過mapred.job.reuse.jvm.num.tasks=1
可以設(shè)置每個JVM 執(zhí)行的 task 數(shù)量
為什么默認(rèn)值是1 赂毯?
因為如果JVM設(shè)置的task數(shù)量超過1,那么這個JVM只有等待其執(zhí)行完自己指定的任務(wù)烦感,或者整個 job執(zhí)行完成才會退出釋放資源膛堤。
我們可以來假設(shè)一下,我們有 6 個task分別是 1肥荔,2,3中符,4,5誉帅,6淀散。對應(yīng)執(zhí)行的JVM 是 1到6 號,其中 1 需要1min 執(zhí)行完吧凉,其余的都是1s執(zhí)行完踏志,如果一個jvm執(zhí)行完一個任務(wù)就退出胀瞪,那么可能在 2s 到 3s 的時候,就只有 1號JVM 占用資源了圆雁,而如果不是帆谍,2到6號 在 2-3s 執(zhí)行完畢,但是因為有重用功能汛蝙,會導(dǎo)致這幾個 JVM 繼續(xù)等待其他任務(wù)的派發(fā),直到 1號JVM 執(zhí)行完畢才會釋放 坚洽,導(dǎo)致資源的浪費。
所以才資源不是很充足的情況下鞍盗,該功能還是要慎用噢~跳昼!
- 控制 Map 和 Reduce 數(shù)量
可以參考這篇文章
這里啰嗦一下兵怯,reduce的數(shù)量可能需要根據(jù)你自己的業(yè)務(wù)來設(shè)置一下,
沒什么可說历帚,但是 Map 一般都不會需要自己設(shè)置和優(yōu)化杠娱,
因為默認(rèn)一個 Map就是對應(yīng) hdfs 上的一個 block,
當(dāng)hdfs block設(shè)置合理禽拔,并且小文件很少的情況室叉,
那么 Map 一般也還算合理并不會有多大影響。
Hive Shell
hive shell 就和 mysql shell 差不多的使用方式茧痕,
支持 repl 的方式進行數(shù)據(jù)查詢,
這里我們主要來說明兩個特殊的使用
- 支持 Hadoop 命令:
hive shell 是支持 hadoop 的相關(guān)操作的曼氛,比如:hive> dfs -ls /
- 支持 Linux 命令:
hive shell 是支持 Linux 的相關(guān)操作的令野,前面加上!
就 ok 了,比如:hive> !ls /
遠程調(diào)試
通過 hive --debug port=9999
來開啟遠程調(diào)聊浅,關(guān)于java 遠程調(diào)試可以參考其他文章
小文件合并
可以參考:https://blog.csdn.net/yycdaizi/article/details/43341239
數(shù)據(jù)倉庫建模
其他小知識點
- hive對科學(xué)計數(shù)法字符串的轉(zhuǎn)換:https://blog.csdn.net/fengyuanshen/article/details/49884291