來源:https://mp.weixin.qq.com/s/NdvHxOtVB7AS5P75QdVO7Q
正文目錄
-
1、表層面
-
1.1 利用分區表優化
-
1.2 利用分桶表優化
-
1.3 選擇合適的文件存儲格式
-
1.4 選擇合適的壓縮格式
-
2、HQL層面優化
-
2.1 執行計划
-
2.1 列、行、分區裁剪
-
2.2 謂詞下推
-
2.3 合並小文件
-
2.4 合理設置MapTask並行度
-
2.5 合理設置ReduceTask並行度
-
2.6 Join優化
-
2.7 CBO優化
-
2.8 Group By優化
-
2.9 Order By優化
-
2.10 Count Distinct 優化
-
2.11 怎樣寫in/exists語句
-
2.12 使用 vectorization 矢量查詢技術
-
2.13 多重插入模式
-
2.14 啟動中間結果壓縮
-
3、Hive架構層面
-
3.1 啟用本地抓取(默認開啟)
-
3.2 本地執行優化
-
3.3 JVM重用
-
3.4 並行執行
-
3.5 推測執行
-
3.6 Hive嚴格模式
-
4、數據傾斜
-
4.1 不同數據類型關聯產生數據傾斜
-
4.2 空值過濾
-
4.3 group by
-
4.4 map join
-
4.5 開啟數據傾斜是負載均衡
-
5、調優方案
-
5.1 日志表和用戶表做鏈接
-
5.2 位圖法求連續七天發朋友圈的用戶
正文
1、表層面
1.1 利用分區表優化
分區表 是在某一個或者幾個維度上對數據進行分類存儲,一個分區對應一個目錄。如果篩選條件里有分區字段,那么 Hive 只需要遍歷對應分區目錄下的文件即可,不需要遍歷全局數據,使得處理的數據量大大減少,從而提高查詢效率。
也就是說:當一個 Hive 表的查詢大多數情況下,會根據某一個字段進行篩選時,那么非常適合創建為分區表,該字段即為分區字段。
CREATE TABLE page_view (viewTime INT, userid BIGINT, page_url STRING, referrer_url STRING, ip STRING COMMENT 'IP Address of the User') PARTITIONED BY(date STRING, country STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '1' STORED AS TEXTFILE;
1、當你意識到一個字段經常用來做where,建分區表,使用這個字段當做分區字段
2、在查詢的時候,使用分區字段來過濾,就可以避免全表掃描。只需要掃描這張表的一個分區的數據即可
1.2 利用分桶表優化
跟分區的概念很相似,都是把數據分成多個不同的類別
1、分區:按照字段值來進行,一個分區,就只是包含這個值的所有記錄
不是當前分區的數據一定不在當前分區
當前分區也只會包含當前這個分區值的數據
2、分桶:默認規則,Hash的方式
一個桶中會有多個不同的值
如果一個分桶中,包含了某個值,這個值的所有記錄,必然都在這個分桶里面
Hive Bucket,分桶,是指將數據以指定列的值為key進行hash,hash到指定數目的桶里面,這樣做的目的和分區表類似,是的篩選時不用全局遍歷所有的數據,只需要遍歷所在的桶就好了,這樣也只可以支持高效采樣。
其實最主要的作用就是 采樣、join
如下例就是以 userid 這一列為 bucket 的依據,共設置 32 個 buckets
CREATE TABLE page_view(viewTime INT, userid BIGINT, page_url STRING, referrer_url STRING, ip STRING COMMENT 'IP Address of the User') COMMENT 'This is the page view table' PARTITIONED BY(dt STRING, country STRING) CLUSTERED BY(userid) SORTED BY(viewTime) INTO 32 BUCKETS
CLUSTERED BY(userid): 按照userid進行分桶
SORTED BY(viewTime): 按照viewTime進行桶內排序
INTO 32 BUCKETS: 分成多少個桶
兩個表以相同方式(相同字段)划分桶,兩個表的桶個數一定是倍數關系,這樣在join的時候速度會大大增加
采樣用的不多,也就不過多闡述了
1.3 選擇合適的文件存儲格式
在 HiveSQL 的 create table 語句中,可以使用 stored as … 指定表的存儲格式。Apache Hive支持 Apache Hadoop 中使用的幾種熟悉的文件格式,比如 TextFile、SequenceFile、RCFile、Avro、ORC、ParquetFile等。存儲格式一般需要根據業務進行選擇,在我們的實操中,絕大多數表都采用TextFile與Parquet兩種存儲格式之一。TextFile是最簡單的存儲格式,它是純文本記錄,也是Hive的默認格式。雖然它的磁盤開銷比較大,查詢效率也低,但它更多地是作為跳板來使用。RCFile、ORC、Parquet等格式的表都不能由文件直接導入數據,必須由TextFile來做中轉。Parquet和ORC都是Apache旗下的開源列式存儲格式。列式存儲比起傳統的行式存儲更適合批量OLAP查詢,並且也支持更好的壓縮和編碼。創建表時,特別是寬表,盡量使用 ORC、ParquetFile 這些列式存儲格式,因為列式存儲的表,每一列的數據在物理上是存儲在一起的,Hive查詢時會只遍歷需要列數據,大大減少處理的數據量。
TextFile
1、存儲方式:行存儲。默認格式,如果建表時不指定默認為此格式。,
2、每一行都是一條記錄,每行都以換行符"\n"結尾。數據不做壓縮時,磁盤會開銷比較大,數據解析開銷也
比較大。
3、可結合Gzip、Bzip2等壓縮方式一起使用(系統會自動檢查,查詢時會自動解壓),推薦選用可切分的壓
縮算法。
Sequence File
1、一種Hadoop API提供的二進制文件,使用方便、可分割、個壓縮的特點。
2、支持三種壓縮選擇:NONE、RECORD、BLOCK。RECORD壓縮率低,一般建議使用BLOCK壓縮
RC File
1、存儲方式:數據按行分塊,每塊按照列存儲 。
A、首先,將數據按行分塊,保證同一個record在一個塊上,避免讀一個記錄需要讀取多個block。
B、其次,塊數據列式存儲,有利於數據壓縮和快速的列存取。
2、相對來說,RCFile對於提升任務執行性能提升不大,但是能節省一些存儲空間。可以使用升級版的ORC格
式。
ORC File
1、存儲方式:數據按行分塊,每塊按照列存儲
2、Hive提供的新格式,屬於RCFile的升級版,性能有大幅度提升,而且數據可以壓縮存儲,壓縮快,快速列存取。
3、ORC File會基於列創建索引,當查詢的時候會很快。
Parquet File
1、存儲方式:列式存儲。
2、Parquet對於大型查詢的類型是高效的。對於掃描特定表格中的特定列查詢,Parquet特別有用。Parquet一般使用Snappy、Gzip壓縮。默認Snappy。
3、Parquet支持Impala 查詢引擎。
4、表的文件存儲格式盡量采用Parquet或ORC,不僅降低存儲量,還優化了查詢,壓縮,表關聯等性能
1.4 選擇合適的壓縮格式
Hive 語句最終是轉化為 MapReduce 程序來執行的,而 MapReduce 的性能瓶頸在與 網絡IO 和 磁盤IO,要解決性能瓶頸,最主要的是 減少數據量,對數據進行壓縮是個好方式。壓縮雖然是減少了數據量,但是壓縮過程要消耗 CPU,但是在 Hadoop 中,往往性能瓶頸不在於 CPU,CPU 壓力並不大,所以壓縮充分利用了比較空閑的 CPU。
常用壓縮方法對比
| 壓縮格式 | 是否可拆分 | 是否自帶 | 壓縮率 | 速度 | 是否hadoop自帶 |
|---|---|---|---|---|---|
| gzip | 否 | 是 | 很高 | 比較快 | 是 |
| lzo | 是 | 是 | 比較高 | 很快 | 否 |
| snappy | 否 | 是 | 比較高 | 很快 | 否 |
| bzip2 | 是 | 否 | 最高 | 慢 | 是 |
壓縮率對比

如何選擇壓縮方式呢?
1、壓縮比例
2、解壓縮速度
3、是否支持split
支持切割的文件可以並行的有多個mapper程序處理大數據文件,一般我們選擇的都是支持切分的!
壓縮帶來的缺點和優點
1、計算密集型,不壓縮,否則會進一步增加cpu的負擔,真實的場景中hive對cpu的壓力很小
2、網絡密集型,推薦壓縮,減小網絡數據傳輸
# Job 輸出文件按照 Block ## 默認值是false set mapreduce.output.fileoutputformat.compress=true; ## 默認值是Record set mapreduce.output.fileoutputformat.compress.type=BLOCK; set mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.lzo.LzoCodec; # Map 輸出結結果進行壓縮 set mapred.map.output.compress=true; set mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.lzo.LzoCodec; # 對 Hive 輸出結果和中間都進行壓縮 set hive.exec.compress.output=true ## 默認值是false,不壓縮 set hive.exec.compress.intermediate=true ## 默認值是false,為true時MR設置的壓縮才啟用
