Hive調優及優化的12種方式


Hive調優及優化的12種方式

請記住:在數據處理中,不怕數據量大,就怕數據傾斜!

針對於Hive內部調優的一些方式

01.請慎重使用COUNT(DISTINCT col);

原因:

distinct會將b列所有的數據保存到內存中,形成一個類似hash的結構,速度是十分的塊;但是在大數據背景下,因為b列所有的值都會形成以key值,極有可能發生OOM

解決方案:

所以,可以考慮使用Group By 或者 ROW_NUMBER() OVER(PARTITION BY col)方式代替COUNT(DISTINCT col)

02.小文件會造成資源的多度占用以及影響查詢效率

原因:

  • 眾所周知,小文件在HDFS中存儲本身就會占用過多的內存空間,那么對於MR查詢過程中過多的小文件又會造成啟動過多的Mapper Task, 每個Mapper都是一個后台線程,會占用JVM的空間
  • 在Hive中,動態分區會造成在插入數據過程中,生成過多零碎的小文件(請回憶昨天講的動態分區的邏輯)
  • 不合理的Reducer Task數量的設置也會造成小文件的生成,因為最終Reducer是將數據落地到HDFS中的

解決方案:

在數據源頭HDFS中控制小文件產生的個數,比如

  • 采用Sequencefile作為表存儲格式,不要用textfile,在一定程度上可以減少小文件(常見於在流計算的時候采用Sequencefile格式進行存儲)
  • 減少reduce的數量(可以使用參數進行控制)
  • 慎重使用動態分區,最好在分區中指定分區字段的val值
  • 最好數據的校驗工作,比如通過腳本方式檢測hive表的文件數量,並進行文件合並
  • 合並多個文件數據到一個文件中,重新構建表

 

03.請慎重使用SELECT *

原因:

在大數據量多字段的數據表中,如果使用 SELECT * 方式去查詢數據,會造成很多無效數據的處理,會占用程序資源,造成資源的浪費

解決方案:

在查詢數據表時,指定所需的待查字段名,而非使用 * 號

04.不要在表關聯后面加WHERE條件

原因:

比如以下語句:

SELECT * FROM stu as t

LEFT JOIN course as t1

ON t.id=t2.stu_id

WHERE t.age=18;

請思考上面語句是否具有優化的空間?如何優化?

解決方案:

采用謂詞下推的技術,提早進行過濾有可能減少必須在數據庫分區之間傳遞的數據量

謂詞下推的解釋:

所謂謂詞下推就是通過嵌套的方式,將底層查詢語句盡量推到數據底層去過濾,這樣在上層應用中就可以使用更少的數據量來查詢,這種SQL技巧被稱為謂詞下推(Predicate pushdown)

那么上面語句就可以采用這種方式來處理:

SELECT * FROM (SELECT * FROM stu WHERE age=18) as t

LEFT JOIN course AS t1

on t.id=t1.stu_id

05.處理掉字段中帶有空值的數據

原因:

一個表內有許多空值時會導致MapReduce過程中,空成為一個key值,對應的會有大量的value值, 而一個key的value會一起到達reduce造成內存不足

解決方式:

1、在查詢的時候,過濾掉所有為NULL的數據,比如:

create table res_tbl as

select n.* from

(select * from res where id is not null ) n

left join org_tbl o on n.id = o.id;

2、查詢出空值並給其賦上隨機數,避免了key值為空(數據傾斜中常用的一種技巧)

create table res_tbl as

select n.* from res n

full join org_tbl o on

case when n.id is null then concat('hive', rand()) else n.id end = o.id;

06.設置並行執行任務數

通過設置參數 hive.exec.parallel 值為 true,就可以開啟並發執行。不過,在共享集群中,需要注意下,如果 job 中並行階段增多,那么集群利用率就會增加。

set hive.exec.parallel=true; //打開任務並行執行

set hive.exec.parallel.thread.number=16; //同一個 sql 允許最大並行度,默認為 8

07.設置合理的Reducer個數

原因:

  • 過多的啟動和初始化 reduce 也會消耗時間和資源
  • 有多少個Reduer就會有多少個文件產生,如果生成了很多個小文件,那么如果這些小文件作為下一個任務的輸入,則也會出現小文件過多的問題

解決方案:

Reducer設置的原則:

每個Reduce處理的數據默認是256MB

hive.exec.reducers.bytes.per.reducer=256000000

每個任務最大的reduce數,默認為1009

hive.exec.reducers.max=1009

計算reduce數的公式

N=min(參數2,總輸入數據量/參數1)

設置Reducer的數量

set mapreduce.job.reduces=n

08.JVM重用

JVM重用是Hadoop中調優參數的內容,該方式對Hive的性能也有很大的幫助,特別對於很難避免小文件的場景或者Task特別多的場景,這類場景大數據書執行時間都很短

Hadood的默認配置通常是使用派生JVM來執行map和reduce任務的,會造成JVM的啟動過程比較大的開銷,尤其是在執行Job包含有成百上千個task任務的情況。

JVM重用可以使得JVM實例在同一個job中重新使用N次,N的值可以在hadoop的mapred-site.xml文件中進行設置

<property>

<name>mapred.job.reuse.jvm.num.tasks</name>

<value>10</value>

</property>

09.為什么任務執行的時候只有一個reduce?

原因:

  • 使用了Order by (Order By是會進行全局排序)
  • 直接COUNT(1),沒有加GROUP BY,比如:
  • SELECT COUNT(1) FROM tbl WHERE pt=’201909’
  • 有笛卡爾積操作

解決方案:

避免使用全局排序,可以使用sort by進行局部排序

使用GROUP BY進行統計,不會進行全局排序,比如:

SELECT pt,COUNT(1) FROM tbl WHERE pt=’201909’;

10.選擇使用Tez引擎

Tez: 是基於Hadoop Yarn之上的DAG(有向無環圖,Directed Acyclic Graph)計算框架。它把Map/Reduce過程拆分成若干個子過程,同時可以把多個Map/Reduce任務組合成一個較大的DAG任務,減少了Map/Reduce之間的文件存儲。同時合理組合其子過程,也可以減少任務的運行時間

設置hive.execution.engine = tez;

通過上述設置,執行的每個HIVE查詢都將利用Tez

當然,也可以選擇使用spark作為計算引擎

11.選擇使用本地模式

有時候Hive處理的數據量非常小,那么在這種情況下,為查詢出發執行任務的時間消耗可能會比實際job的執行時間要長,對於大多數這種情況,hive可以通過本地模式在單節點上處理所有任務,對於小數據量任務可以大大的縮短時間

可以通過

hive.exec.mode.local.auto=true

12.選擇使用嚴格模式

Hive提供了一種嚴格模式,可以防止用戶執行那些可能產生意想不到的不好的影響查詢

比如:

  • 對於分區表,除非WHERE語句中含有分區字段過濾條件來限制數據范圍,否則不允許執行,也就是說不允許掃描所有分區
  • 使用ORDER BY 語句進行查詢是,必須使用LIMIT語句,因為ORDER BY 為了執行排序過程會將所有結果數據分發到同一個reduce中進行處理,強制要求用戶添加LIMIT可以防止reducer額外的執行很長時間

嚴格模式的配置:

Hive.mapred.mode=strict


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM