備註:
Hive 版本 2.1.1
一.Hive的實現原理
Hive的編譯器將HQL轉換成一組操作符(Operator)
操作符是Hive的最小處理單元
每個操作符代表一道HDFS操作或者MR Job 作業
Hive的操作符
Hive編譯器
Parser:
將SQL轉換成抽象語法樹
語法解析器:
將抽象語法樹轉換成查詢塊
邏輯計劃生成器:
將查詢塊轉換成邏輯計劃
物理計劃生成器:
將邏輯計劃轉換成物理計劃
物理計劃優化器:
物理計劃優化策略
編譯流程
利用Explain查看執行計劃
語法:
:EXPLAIN [EXTENDED] query
輸出:
- 查詢語句的抽象語法樹(AST)
- 執行計劃丌同階段間的依賴關係
- 每個階段的描述
二Hive優化
優化的目的:提升查詢性能,快速產出結果
Hive的優化思路:
- 編譯器優化器優化:採用合理的優化策略,生成高效的物理計劃
- MapReduce執行層優化:通過MR參數優化,提升Job運行效率
- HDFS存儲層優化:採用合理的存儲格式和合理的Schema設計,降低IO瓶頸
2.1 選擇合理的存儲格式和壓縮格式
列存儲,高壓縮比,列剪枝,過濾無用字段IO
- Orc
- Parquet
壓縮格式選擇:snappy
2.2 MR Job優化
並行執行
Hive產生的MR Job默認是順序執行的,如果Job之間無依賴可以並行執行
set hive.exec.parallel=true;
本地執行
雖然Hive能夠利用MR處理大規模數據,但某些場景下處理的數據量非常小可以本地執行,不必提交集羣
set hive.exec.mode.local.auto=true;
hive.exec.mode.local.auto.inputbytes.max(默認128MB)
hive.exec.mode.local.auto.input.files.max(默認4)
合併輸入小文件
如果Job輸入有很多小文件,造成Map數太多,影響效率
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
合併輸出小文件
set hive.merge.mapfiles=true; // map only job結束時合併小文件
set hive.merge.mapredfiles=true; // 合併reduce輸出的小文件
set hive.merge.smallfiles.avgsize=256000000; //當輸出文件平均大小小於該值,啓動新job合併文件
set hive.merge.size.per.task=64000000; //合併之後的每個文件大小
控制Map/Reduce數
控制Map/Reduce數來控制Job執行的並行度
Num_Map_tasks= $inputsize/ max($mapred.min.split.size, min($dfs.block.size, $mapred.max.split.size))
Num_Reduce_tasks= min($hive.exec.reducers.max, $inputsize/$hive.exec.reducers.bytes.per.reducer)
JVM重用
JVM重利用可以使job長時間保留slot,直到作業結束
set mapred.job.reuse.jvm.num.tasks=10 //每個jvm運行10個task
推測執行
set hive.mapred.reduce.tasks.speculative.execution=true
set mapreduce.map.speculative=true
set mapreduce.reduce.speculative=true
一定要開啓壓縮
中間結果壓縮,減少Job跟Job之間的IO開銷
set hive.exec.compress.intermediate=true
set mapred.map.output.compression.codec=<CodecClassName>
最終結果壓縮,減少存儲空間
set hive.exec.compress.output=true
Set mapred.output.compression.codec=<CodecClassName>
2.3 Join優化
Hive的Join類型:
- Shuffle Join
- Broadcast Join(MapJoin)
-
Sort-Merge-Bucket Join
2.3.1 MapJoin 優化
方式一(自動判斷):
set.hive.auto.convert.join=true;
hive.mapjoin.smalltable.filesize // 默認值是25mb, 小表小於25mb自動啓動mapjoin
方式二(手動顯式):
select /+mapjoin(A)/ f.a,f.bfrom A t join B f on (f.a=t.a)
2.3.2 SMB Join 優化
使用方式:
hive.optimize.bucketmapjoin= true
和mapjoin一起工作,所有要Join的表都必須對Join key做了分桶,並且大表的桶數是小表的整數倍
由於對錶設計有太多的限制,不太常用
2.4 數據傾斜
數據傾斜是指由於數據分佈不均勻,個別值集中佔據大部分數據量,導致某一個或者幾個ReduceTask處理的數據量相對很大造成的Job運行非常慢,甚至OOM掛掉
在SQL上,一般是由於group by 或者join shuffle key丌均勻造成的
數據傾斜是業務數據問題導致的,如果從業務上下手避免是最好的
- 比如由於Null值引起的,或者某一個特殊的key造成的數據量特別大
- 先過濾掉特殊key的數據再進行處理
Hive自身的優化方案:
- 由group by 引起的數據傾斜:
hive.map.aggr=true //做map端預聚合,相當於Map端Combiner
hive.groupby.skewindata//將key的數據隨機分發到Reduce端做聚合,然後再起一個Job對上一步的結果做聚合
- 由Join引起的數據傾斜(Skew Join)
set hive.optimize.skewjoin= true
set hive.skewjoin.key= 100000
// 超過閾值就判斷爲skew key
2.5 Hive的優化配置參數
hive-site.xml中更改默認配置
在腳本中set變量
Hive的優化配置非常多,具體情況具體分析