Hive效能調優實踐 - Vidhya

banq發表於2022-02-20

Apache Hive 是一個建立在 Hadoop 之上的資料倉儲系統,它使使用者能夠靈活地以類似 SQL 的查詢的形式編寫複雜的 MapReduce 程式。效能調優是執行 Hive 查詢的重要部分,因為它可以幫助程式設計師減少時間並提高程式碼效率。應用正確的方法並使用最佳最佳化實踐,我們可以在 hive 查詢的時間和儲存方面取得重大的里程碑,並提高叢集的效能,而效能調優在這裡發揮了重要作用。 
在這篇文章中,我想分享一些效能調優配置和查詢的實踐,我發現這些實踐在使用 Hive 時很有效。
首先,讓我們瞭解調整 Hive 查詢的步驟:
  1. 識別:在這一步中,我們列出了所有消耗更多時間的 Hive 程式碼。
  2. 調整:我們在不干擾程式碼功能的情況下找出最佳解決方案,並確保改進程式碼。
  3. 測試和部署:我們測試更改的程式碼,然後將其部署到生產中。我們應該監控幾天更改程式碼的執行時間。
  4. 測量: 在這一步中,我們隨時測量更改的程式碼是否在改進。此外,將更改程式碼的新執行時間與過去的生產時間進行比較。
  5. 繼續改進: 我們一直在尋找可能的解決方案以進一步改進。

 

效能調優技術的型別
有幾種 Hive 最佳化技術可以提高其效能,我們可以在執行 Hive 查詢時實施這些技術,從而也關注效能調優:

1 避免鎖定表
確保在任何 Hive 查詢中都使用表是非常重要的,因為源沒有被另一個程式使用。這可能導致表被鎖定,我們的查詢可能會被卡住一段未知的時間。
我們可以使用下面的引數來確保表沒有被鎖定:

set hive.support.concurrency=false;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager;
set hive.bin.strict.locking.mode=false;


 

2 使用Hive的執行引擎TEZ
在執行Hive查詢時,TEZ執行引擎是首選,因為它消除了不必要的磁碟訪問。它從磁碟中獲取一次資料,進行計算,併產生輸出,從而使我們免於多次磁碟遍歷。我們可以認為TEZ是map-reduce框架的一個更靈活、更強大的繼承者。

我們可以設定下面的引數來使用TEZ引擎。

[i]set hive.execution.engine=tez;[/i]

  

3 使用Hive基於成本的最佳化器(CBO)
Apache Hive提供了一個基於成本的最佳化器來提高效能。它透過檢查查詢成本來生成有效的執行計劃,比如如何排序連線、執行哪種型別的連線、並行程度等等。這些決定由ANALYZE語句或元儲存本身收集,最終削減查詢執行時間並減少資源利用率。

我們可以來設定引數。

set hive.cbo.enable=true;

 

4 在Mapper和Reducer層面的並行執行
我們可以透過使用向量查詢執行來提高hive查詢的聚合、過濾和連線的效能,這意味著我們可以一次性分批掃描1024條記錄,而不是每次都掃描一條記錄。

我們應該探索以下的引數,這將有助於帶來更多的並行性,並大大改善查詢執行時間。

set hive.vectorized.execution.enabled=true; 
set hive.exec.parallel=true;


類如:

Select a.*, b.* from
(select * from table1 ) a
Join
(select * from table2 ) b
On a.id=b.id
;


我們可以看到這兩個子查詢是獨立的,所以這可能會增加效率。

需要注意的一個重要問題是,並行執行會增加叢集的利用率。如果一個叢集的利用率已經很高了,並行執行就不會有什麼幫助。
 

5 使用STREAMTABLE選項
當我們要連線多個表時,我們可以使用STREAMTABLE選項。預設情況下,最右邊的表會被流化。

比如說。如果我們連線兩個表'huge_table'和'small_table',預設情況下,'small_table'被流化,因為它是最右邊的表。在這種情況下,'huge_table',作為較大的表,將試圖被緩衝到記憶體中,並可能導致java堆空間問題或作業執行時間更長。在這種情況下,我們可以做的是新增/*+ STREAMTABLE('huge_table') */,這將使'huge_table'被流化而不是進入記憶體。

因此,透過這種方式,我們可以不用記住連線表的順序。
 

6 使用Map Side JOIN選項
如果連線中的一個表是一個小表,並且可以被載入到記憶體中,我們可以強制使用MAPSIDE連線,如下所示。

Select /*+ MAPJOIN(small_table) */ large_table.col1,large_table.col2 from large_table join small_table on large_table.col1 = small_table.col1;


map端連線可以在對映器中執行,而無需使用Map/Reduce步驟。

另外,我們可以透過設定auto.convert.join為True,讓執行引擎來處理這個問題。

set auto.convert.join = True :


 

7.避免在JOIN和WHERE子句中使用計算欄位
我們應該避免在JOIN和WHERE子句中使用任何計算欄位,因為它們需要花費很長的時間來執行Hive查詢。我們可以使用CTE(Create table expression)來處理這些功能,並且可以最佳化我們的查詢。

比如說, 原始查詢:

select a.coll, b.col2 from table1 as a join table2 as b on (a.coll +50 = b.col2);


使用CTE 最佳化後:

(select a.col1 + 50 as C1 FROM table1 )
select CTE.C1, b.col2 from CTE join table2 b on (CTE.C1 = b.col2);

 

8 使用SORT BY而不是ORDER BY
Hive支援ORDER BY和SORT BY兩種原因。ORDER BY在單一的還原器上工作,它會導致效能瓶頸。但是,SORT BY只在每個減速器內對資料進行排序,並執行本地排序,每個減速器的輸出都將被排序,確保更好的效能。

9 選擇需要的列
當我們使用Hive時,如果我們只需要一個表中的幾列,請避免使用SELECT * FROM,因為這會增加不必要的執行時間。
 

10 適當的輸入格式選擇
在資料的基礎上使用合適的檔案格式可以大大增加我們的查詢效能。Hive帶有柱狀輸入格式,如RCFile、ORC等。與Text、Sequence和RC檔案格式相比,ORC顯示出更好的效能,因為Hive有一個向量的ORC閱讀器,透過允許單獨訪問每一列,可以減少分析查詢中的讀取操作。
 

11 儘可能早地限制(過濾)資料 
這是任何調整的基本原則,在這個過程中,我們提前過濾或放棄記錄,這樣就可以避免處理長期執行的查詢和處理不必要的結果。
例如:

a join b where a.col !=null
寫成:

 (select * from a where a.col!=null) join b

  

12 使用多查詢插入
在這裡,我們將有一個共同的資料集(Superset),然後我們將根據WHERE子句中指定的特定條件,使用它來插入多個表。當多個表有共同的超級資料集時,這有助於並行載入這些表。
 

13 將程式碼模組化為邏輯片段
這有助於對程式碼的維護。也有助於在失敗的情況下重新啟動工作。這可以透過執行相互獨立的模組來實現並行化,從而節省時間。
 

相關文章