數棧技術分享:Hive優化之配置參數的優化

Hive是大數據領域經常使用的組件之一,主要用於大數據離線數倉的運算,關於Hive的性能調優在平常工做和麪試中是常常涉及的一個點,所以掌握一些Hive調優是必不可少的一項技能。影響Hive效率的主要因素有數據傾斜、數據冗餘、job的IO以及不一樣底層引擎配置狀況和Hive自己參數和HiveSQL的執行等。本文主要從建表配置參數方面對Hive優化進行講解。node

1. 建立一個普通表git

table test_user1(id int, name string,code string,code_id string ) ROW FORMAT DELIMITED FIELDS TERMINATED  BY ',';

2. 查看這張表的信息github

DESCRIBE FORMATTED  test_user1;

咱們從該表的描述信息介紹建表時的一些可優化點。面試

2.1 表的文件數算法

numFiles表示表中含有的文件數,當文件數過多時可能意味着該表的小文件過多,這時候咱們能夠針對小文件的問題進行一些優化,HDFS自己提供瞭解決方案:apache

(1)Hadoop Archive/HAR:將小文件打包成大文件。app

(2)SEQUENCEFILE格式:將大量小文件壓縮成一個SEQUENCEFILE文件。框架

(3)CombineFileInputFormat:在map和reduce處理以前組合小文件。工具

(4)HDFS Federation:HDFS聯盟,使用多個namenode節點管理文件。oop

除此以外,咱們還能夠經過設置hive的參數來合併小文件。

(1)輸入階段合併

須要更改Hive的輸入文件格式,即參數hive.input.format,默認值是org.apache.hadoop.hive.ql.io.HiveInputFormat,咱們改爲org.apache.hadoop.hive.ql.io.CombineHiveInputFormat。這樣比起上面對mapper數的調整,會多出兩個參數,分別是mapred.min.split.size.per.node和mapred.min.split.size.per.rack,含義是單節點和單機架上的最小split大小。若是發現有split大小小於這兩個值(默認都是100MB),則會進行合併。具體邏輯能夠參看Hive源碼中的對應類。

(2)輸出階段合併

直接將hive.merge.mapfiles和hive.merge.mapredfiles都設爲true便可,前者表示將map-only任務的輸出合併,後者表示將map-reduce任務的輸出合併,Hive會額外啓動一個mr做業將輸出的小文件合併成大文件。另外,hive.merge.size.per.task能夠指定每一個task輸出後合併文件大小的指望值,hive.merge.size.smallfiles.avgsize能夠指定全部輸出文件大小的均值閾值,默認值都是1GB。若是平均大小不足的話,就會另外啓動一個任務來進行合併。

2.2 表的存儲格式

經過InputFormat和OutputFormat能夠看出表的存儲格式是TEXT類型,Hive支持TEXTFILE, SEQUENCEFILE, AVRO, RCFILE, ORC,以及PARQUET文件格式,能夠經過兩種方式指定表的文件格式:

(1)CREATE TABLE ... STORE AS <file_format>:在建表時指定文件格式,默認是TEXTFILE

(2)ALTER TABLE ... [PARTITION partition_spec] SET FILEFORMAT <file_format>:修改具體表的文件格式

若是要改變建立表的默認文件格式,可使用set hive.default.fileformat=<file_format>進行配置,適用於全部表。同時也可使用set hive.default.fileformat.managed = <file_format>進行配置,僅適用於內部表或外部表。

擴展:不一樣存儲方式的狀況

TEXT, SEQUENCE和 AVRO文件是面向行的文件存儲格式,不是最佳的文件格式,由於即使只查詢一列數據,使用這些存儲格式的表也須要讀取完整的一行數據。另外一方面,面向列的存儲格式(RCFILE, ORC, PARQUET)能夠很好地解決上面的問題。關於每種文件格式的說明,以下:

(1)TEXTFILE

建立表時的默認文件格式,數據被存儲成文本格式。文本文件能夠被分割和並行處理,也可使用壓縮,好比GZip、LZO或者Snappy。然而大部分的壓縮文件不支持分割和並行處理,會形成一個做業只有一個mapper去處理數據,使用壓縮的文本文件要確保文件不要過大,通常接近兩個HDFS塊的大小。

(2)SEQUENCEFILE

key/value對的二進制存儲格式,sequence文件的優點是比文本格式更好壓縮,sequence文件能夠被壓縮成塊級別的記錄,塊級別的壓縮是一個很好的壓縮比例。若是使用塊壓縮,須要使用下面的配置:set hive.exec.compress.output=true; set io.seqfile.compression.type=BLOCK

(3)AVRO

二進制格式文件,除此以外,avro也是一個序列化和反序列化的框架。avro提供了具體的數據schema。

(4)RCFILE

全稱是Record Columnar File,首先將表分爲幾個行組,對每一個行組內的數據進行按列存儲,每一列的數據都是分開存儲,即先水平劃分,再垂直劃分。

(5)ORC

全稱是Optimized Row Columnar,從hive0.11版本開始支持,ORC格式是RCFILE格式的一種優化的格式,提供了更大的默認塊(256M)

(6)PARQUET

另一種列式存儲的文件格式,與ORC很是相似,與ORC相比,Parquet格式支持的生態更廣,好比低版本的impala不支持ORC格式。

配置一樣數據一樣字段的兩張表,以常見的TEXT行存儲和ORC列存儲兩種存儲方式爲例,對比執行速度。

TEXT存儲方式

總結:從上圖中能夠看出列存儲在對指定列進行查詢時,速度更快,建議在建表時設置列存儲的存儲方式

2.3 表的壓縮

對Hive表進行壓縮是常見的優化手段,一些存儲方式自帶壓縮選擇,好比SEQUENCEFILE支持三種壓縮選擇:NONE,RECORD,BLOCK。Record壓縮率低,通常建議使用BLOCK壓縮;

ORC支持三種壓縮選擇:NONE,ZLIB,SNAPPY。咱們以TEXT存儲方式和ORC存儲方式爲例,查看錶的壓縮狀況。

配置一樣數據一樣字段的四張表,一張TEXT存儲方式,另外三張分別是默認壓縮方式的ORC存儲、SNAPPY壓縮方式的ORC存儲和NONE壓縮方式的ORC存儲,查看在hdfs上的存儲狀況:

TEXT存儲方式

 

默認壓縮ORC存儲方式

 

SNAPPY壓縮的ORC存儲方式

 

NONE壓縮的ORC存儲方式

 

總結:能夠看到ORC存儲方式將數據存放爲兩個block,默認壓縮大小加起來134.69M,SNAPPY壓縮大小加起來196.67M,NONE壓縮大小加起來247.55M,TEXT存儲方式的文件大小爲366.58M,且默認block兩種存儲方式分別爲256M和128M,ORC默認的壓縮方式比SNAPPY壓縮獲得的文件還小,緣由是ORZ默認的ZLIB壓縮方式採用的是deflate壓縮算法,比Snappy壓縮算法獲得的壓縮比高,壓縮的文件更小。ORC不一樣壓縮方式之間的執行速度,通過屢次測試發現三種壓縮方式的執行速度差很少,因此建議採用ORC默認的存儲方式進行存儲數據。

2.4 分桶分區

Num Buckets表示桶的數量,咱們能夠經過分桶和分區操做對Hive表進行優化:

對於一張較大的表,能夠將它設計成分區表,若是不設置成分區表,數據是全盤掃描的,設置成分區表後,查詢時只在指定的分區中進行數據掃描,提高查詢效率。要注意儘可能避免多級分區,通常二級分區足夠使用。常見的分區字段:

(1)日期或者時間,好比year、month、day或者hour,當表中存在時間或者日期字段時,可使用些字段。

(2)地理位置,好比國家、省份、城市等

(3)業務邏輯,好比部門、銷售區域、客戶等等

與分區表相似,分桶表的組織方式是將HDFS上的一張大表文件分割成多個文件。分桶是相對分區進行更細粒度的劃分,分桶將整個數據內容按照分桶字段屬性值得hash值進行區分,分桶能夠加快數據採樣,也能夠提高join的性能(join的字段是分桶字段),由於分桶能夠確保某個key對應的數據在一個特定的桶內(文件),因此巧妙地選擇分桶字段能夠大幅度提高join的性能。一般狀況下,分桶字段能夠選擇常常用在過濾操做或者join操做的字段。

建立分桶表

create table test_user_bucket(id int, name string,code string,code_id string ) clustered by(id) into 3 buckets ROW FORMAT DELIMITED FIELDS TERMINATED  BY ',';

查看描述信息

DESCRIBE FORMATTED test_user_bucket

多出了以下信息

查看該表的hdfs

一樣的數據查看普通表和分桶表查詢效率

普通表

分桶表

普通表是全表掃描,分桶表在按照分桶字段的hash值分桶後,根據join字段或者where過濾字段在特定的桶中進行掃描,效率提高。


本文首發於:數棧研習社

數棧是雲原生—站式數據中臺PaaS,咱們在github上有一個有趣的開源項目:FlinkX

FlinkX是一個基於Flink的批流統一的數據同步工具,既能夠採集靜態的數據,好比MySQL,HDFS等,也能夠採集實時變化的數據,好比MySQL binlog,Kafka等,是全域、異構、批流一體的數據同步引擎,你們若是有興趣,歡迎來github社區找咱們玩~

相關文章
相關標籤/搜索