您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關Hive調優技巧有哪些,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
Apache Hive是建立在Apache Hadoop之上的數據倉庫軟件項目,用于提供數據查詢和分析。Hive是Hadoop在HDFS上的SQL接口,它提供了類似于SQL的接口來查詢存儲在與Hadoop集成的各種數據庫和文件系統中的數據。可以說從事數據開發工作,無論是在平時的工作中,還是在面試中,Hive具有舉足輕重的地位,尤其是Hive的性能調優方面,不僅能夠在工作中提升效率而且還可以在面試中脫穎而出。
技巧如下:默認情況下,Hive會執行多次表掃描。因此,如果要在某張hive表中執行多個操作,建議使用一次掃描并使用該掃描來執行多個操作。
比如將一張表的數據多次查詢出來裝載到另外一張表中。如下面的示例,表my_table是一個分區表,分區字段為dt,如果需要在表中查詢2個特定的分區日期數據,并將記錄裝載到2個不同的表中。
INSERT INTO temp_table_20201115 SELECT * FROM my_table WHERE dt ='2020-11-15';
INSERT INTO temp_table_20201116 SELECT * FROM my_table WHERE dt ='2020-11-16';
在以上查詢中,Hive將掃描表2次,為了避免這種情況,我們可以使用下面的方式:
FROM my_table
INSERT INTO temp_table_20201115 SELECT * WHERE dt ='2020-11-15'
INSERT INTO temp_table_20201116 SELECT * WHERE dt ='2020-11-16'
這樣可以確保只對my_table表執行一次掃描,從而可以大大減少執行的時間和資源。
對于一張比較大的表,將其設計成分區表可以提升查詢的性能,對于一個特定分區的查詢,只會加載對應分區路徑的文件數據,因此,當用戶使用特定分區列值執行選擇查詢時,將僅針對該特定分區執行查詢,由于將針對較少的數據量進行掃描,所以可以提供更好的性能。值得注意的是,分區字段的選擇是影響查詢性能的重要因素,盡量避免層級較深的分區,這樣會造成太多的子文件夾。
現在問題來了,該使用哪些列進行分區呢?一條基本的法則是:選擇低基數屬性作為“分區鍵”,比如“地區”或“日期”等。
一些常見的分區字段可以是:
比如year、month、day或者hour,當表中存在時間或者日期字段時,可以使用些字段。
比如國家、省份、城市等
比如部門、銷售區域、客戶等等
CREATE TABLE table_name (
col1 data_type,
col2 data_type)
PARTITIONED BY (partition1 data_type, partition2 data_type,….);
通常,當很難在列上創建分區時,我們會使用分桶,比如某個經常被篩選的字段,如果將其作為分區字段,會造成大量的分區。在Hive中,會對分桶字段進行哈希,從而提供了中額外的數據結構,進行提升查詢效率。
與分區表類似,分桶表的組織方式是將HDFS上的文件分割成多個文件。分桶可以加快數據采樣,也可以提升join的性能(join的字段是分桶字段),因為分桶可以確保某個key對應的數據在一個特定的桶內(文件),所以巧妙地選擇分桶字段可以大幅度提升join的性能。通常情況下,分桶字段可以選擇經常用在過濾操作或者join操作的字段。
我們可以使用set.hive.enforce.bucketing = true啟用分桶設置。
當使用分桶表時,最好將bucketmapjoin標志設置為true,具體配置參數為:
SET hive.optimize.bucketmapjoin = true
CREATE TABLE table_name
PARTITIONED BY (partition1 data_type, partition2 data_type,….) CLUSTERED BY (column_name1, column_name2, …)
SORTED BY (column_name [ASC|DESC], …)]
INTO num_buckets BUCKETS;
復雜的Hive查詢通常會轉換為一系列多階段的MapReduce作業,并且這些作業將由Hive引擎鏈接起來以完成整個查詢。因此,此處的“中間輸出”是指上一個MapReduce作業的輸出,它將用作下一個MapReduce作業的輸入數據。
壓縮可以顯著減少中間數據量,從而在內部減少了Map和Reduce之間的數據傳輸量。
我們可以使用以下屬性在中間輸出上啟用壓縮。
set hive.exec.compress.intermediate=true;
set hive.intermediate.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;
set hive.intermediate.compression.type=BLOCK;
為了將最終輸出到HDFS的數據進行壓縮,可以使用以下屬性:
set hive.exec.compress.output=true;
下面是一些可以使用的壓縮編解碼器
org.apache.hadoop.io.compress.DefaultCodec
org.apache.hadoop.io.compress.GzipCodec
org.apache.hadoop.io.compress.BZip2Codec
com.hadoop.compression.lzo.LzopCodec
org.apache.hadoop.io.compress.Lz4Codec
org.apache.hadoop.io.compress.SnappyCodec
map端join適用于當一張表很小(可以存在內存中)的情況,即可以將小表加載至內存。Hive從0.7開始支持自動轉為map端join,具體配置如下:
SET hive.auto.convert.join=true; -- hivev0.11.0之后默認true
SET hive.mapjoin.smalltable.filesize=600000000; -- 默認 25m
SET hive.auto.convert.join.noconditionaltask=true; -- 默認true,所以不需要指定map join hint
SET hive.auto.convert.join.noconditionaltask.size=10000000; -- 控制加載到內存的表的大小
一旦開啟map端join配置,Hive會自動檢查小表是否大于hive.mapjoin.smalltable.filesize
配置的大小,如果大于則轉為普通的join,如果小于則轉為map端join。
關于map端join的原理,如下圖所示:
首先,Task A(客戶端本地執行的task)負責讀取小表a,并將其轉成一個HashTable的數據結構,寫入到本地文件,之后將其加載至分布式緩存。
然后,Task B任務會啟動map任務讀取大表b,在Map階段,根據每條記錄與分布式緩存中的a表對應的hashtable關聯,并輸出結果
注意:map端join沒有reduce任務,所以map直接輸出結果,即有多少個map任務就會產生多少個結果文件。
Hive中的向量化查詢執行大大減少了典型查詢操作(如掃描,過濾器,聚合和連接)的CPU使用率。
標準查詢執行系統一次處理一行,在處理下一行之前,單行數據會被查詢中的所有運算符進行處理,導致CPU使用效率非常低。在向量化查詢執行中,數據行被批處理在一起(默認=> 1024行),表示為一組列向量。
要使用向量化查詢執行,必須以ORC格式(CDH 5)存儲數據,并設置以下變量。
SET hive.vectorized.execution.enabled=true
在CDH 6中默認啟用Hive查詢向量化,啟用查詢向量化后,還可以設置其他屬性來調整查詢向量化的方式,具體可以參考cloudera官網。
默認生成的執行計劃會在可見的位置執行過濾器,但在某些情況下,某些過濾器表達式可以被推到更接近首次看到此特定數據的運算符的位置。
比如下面的查詢:
select
a.*,
b.*
from
a join b on (a.col1 = b.col1)
where a.col1 > 15 and b.col2 > 16
如果沒有謂詞下推,則在完成JOIN處理之后將執行過濾條件**(a.col1> 15和b.col2> 16)**。因此,在這種情況下,JOIN將首先發生,并且可能產生更多的行,然后在進行過濾操作。
使用謂詞下推,這兩個謂詞**(a.col1> 15和b.col2> 16)**將在JOIN之前被處理,因此它可能會從a和b中過濾掉連接中較早處理的大部分數據行,因此,建議啟用謂詞下推。
通過將hive.optimize.ppd設置為true可以啟用謂詞下推。
SET hive.optimize.ppd=true
Hive支持TEXTFILE, SEQUENCEFILE, AVRO, RCFILE, ORC,以及PARQUET文件格式,可以通過兩種方式指定表的文件格式:
如果未指定文件存儲格式,則默認使用的是參數hive.default.fileformat設定的格式。
如果數據存儲在小于塊大小的小文件中,則可以使用SEQUENCE文件格式。如果要以減少存儲空間并提高性能的優化方式存儲數據,則可以使用ORC文件格式,而當列中嵌套的數據過多時,Parquet格式會很有用。因此,需要根據擁有的數據確定輸入文件格式。
如果要查詢分區的Hive表,但不提供分區謂詞(分區列條件),則在這種情況下,將針對該表的所有分區發出查詢,這可能會非常耗時且占用資源。因此,我們將下面的屬性定義為strict,以指示在分區表上未提供分區謂詞的情況下編譯器將引發錯誤。
SET hive.partition.pruning=strict
Hive在提交最終執行之前會優化每個查詢的邏輯和物理執行計劃。基于成本的優化會根據查詢成本進行進一步的優化,從而可能產生不同的決策:比如如何決定JOIN的順序,執行哪種類型的JOIN以及并行度等。
可以通過設置以下參數來啟用基于成本的優化。
set hive.cbo.enable=true;
set hive.compute.query.using.stats=true;
set hive.stats.fetch.column.stats=true;
set hive.stats.fetch.partition.stats=true;
可以使用統計信息來優化查詢以提高性能。基于成本的優化器(CBO)還使用統計信息來比較查詢計劃并選擇最佳計劃。通過查看統計信息而不是運行查詢,效率會很高。
收集表的列統計信息:
ANALYZE TABLE mytable COMPUTE STATISTICS FOR COLUMNS;
查看my_db數據庫中my_table中my_id列的列統計信息:
DESCRIBE FORMATTED my_db.my_table my_id
關于“Hive調優技巧有哪些”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。