日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

hive 两个没有null指定的表左关联的结果有null_Hive的优化原则

發布時間:2024/7/23 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hive 两个没有null指定的表左关联的结果有null_Hive的优化原则 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文鏈接:https://zhuanlan.zhihu.com/p/174469951

本篇將 Hive 的優化分成三個部分:

  • 第一部分是 SQL 通用語法優化,
  • 第二部分是針對 Hive 所具有的數據傾斜的優化,
  • 第三部分則介紹一些通用性的 Hive 參數設置優化。

一、語法優化

SQL 的語法優化本質上是如何用更少的計算資源干相同的活,基于此延伸出幾條原則,這幾條原則又拓展出對應的一些具體方法:

原則1:取更少的數

這條原則特別樸素,只要數據量少了運算的效率自然會提升,但如何能夠取更少數的同時不影響結果呢?

1、不要用 select *

這條不多說了,一些寬表少則二三十,多則上百列,而實際絕大多數都是我們不需要的,在 select 時只挑選后續需要用到字段而不是 select *,那么運算時間會成倍減少。

2、謂詞下推

謂詞下推指:

將過濾表達式盡可能移動至靠近數據源的位置,以使真正執行時能直接跳過無關的數據。

簡單來說就是把 where 語句盡可能挪到最底層的位置,在最底層就把不需要的數據都過濾掉,然后讓真正需要的數據參與運算,而不是留到最后才進行過濾。

根據謂詞下推的思想,可對下面的代碼進行優化:

select t1.name, t2.age, t2.class, t2.income from t1 join t2 on t1.id = t2.id where t2.age > 18

優化后:

select t1.name, t2.age, t2.class, t2.income from t1
join
(select id, age, class, income from t2 where id > 18) t2
on t1.id = t2.id

3、多用子查詢

基于謂詞下推的思想,我們還可以做進一步的優化,即多用子查詢,上面的代碼可進一步優化成如下樣子:

select t1.name, t2.age, t2.class, t2.income from
(select id, name from t1) t1
join
(select id, age, class, income from t2 where age > 18) t2
on t1.id = t2.id

采用子查詢后,盡管會增加 job 數但提前把數據完成了過濾,還提高了代碼的可讀性,尤其是當需要關聯的表和條件成倍增加后,可讀性將會非常重要。

4、子查詢的去重

當子查詢的表中所需的字段存在重復值,那么對這些字段提前進行去重再進行關聯同樣會提高運算效率。還是以上面的代碼為例:

select t1.name, t2.age, t2.class, t2.income from
(select id, name from t1) t1
join
(select id, age, class, income from t2 where age > 18 group by id, age, class, income) t2
on t1.id = t2.id

至于為什么用 group by 而不是 distinct 去重會在數據傾斜部分進行解釋。

5、過濾null值

當關聯所用到的字段包含了太多 null 時,需要從業務的角度考慮這些為 null 的數據是否有存在的必要,如果不必要的話盡早過濾掉,避免影響關聯的效率。

如果確實需要用到,則可用 rand() 把數據均勻分布在不同的 reduce 上,避免數據傾斜,詳細可見第二部分,此處僅列出代碼:

select
n.*,
o.name
from
nullidtable n
full join
bigtable o
on nvl(n.id,rand())=o.id

原則2:不排序

SQL 中進行排序是要消耗計算資源的,在 Hive 中這種資源消耗會更加明顯。子查詢里不要排序這一點就不多說了,子查詢中排序是毫無意義的,同時在最后的結果步也盡可能少排序,排序這需求完全可以通過交互查詢的UI或把結果數據導出進行替代解決。當然,如果進行查詢時沒有UI系統,或者不方便把數據導出,或者你就是想即時看到數據的排序情況,就當這條建議不存在就好,但在子查詢里排序仍然還是毫無意義的。

原則3:分步

該原則主要目的是把大數據集拆成小數據集來運行。

1、減少在 selec 時用 case when

有時出結果時需要用 case when 進行分類輸出,如下面例子

select
dt,
count(distinct case when id=1 then user_id else null end) as id_1_cnt,
count(distinct case when id=2 then user_id else null end) as id_2_cnt
from table_1
where dt between '20200511' and '20200915'
group by dt

但是實測發現 case when 的執行效率很低,當數據量太大的時候甚至會跑不出數,因此上面的代碼可優化成如下形式:

select
t1.dt,
t1.id_1_cnt,
t2.id_2_cnt
from
(select
dt,
count(distinct user_id) as id_1_cnt
from table_1
where dt between '20200511' and '20200915' and id=1
group by dt) t1
left join
(select
dt,
count(distinct user_id) as id_2_cnt
from table_1
where dt between '20200511' and '20200915' and id=2
group by dt) t2
on t1.dt=t2.dt

當數據量很大或者 select 時有太多的 case when,采用上面的方式其執行效率會提高 10 倍以上。

2、多用臨時表

當需要建的表其邏輯非常復雜時,需要考慮用臨時表的方式把中間邏輯分布執行,一來方便閱讀、修改和維護,二來減少硬盤的開銷(相較于建中間表的方式)。

3、where+union all

當需要根據某字段分類匯總時發現運行速度很慢甚至跑不出結果,那么有可能是因為某一類型的數據樣本量過大造成數據傾斜,此時可考慮通過 where 過濾 + union all 合并的方法分步統計和匯總來處理該問題。

優化前:

select
age,
count(distinct id) as id_cnt
from age_table
group by age

優化后:

select
age,
count(distinct id) as id_cnt
from age_table
where age<35
group by age
union all
select
age,
count(distinct id) as id_cnt
from age_table
where age>=35
group by age

SQL 語句的優化方法貴精不貴多,牢記上述原則和方法在日常取數建表寫 SQL 時大部分情況下就已經接近最優效率了。

二、數據傾斜

在展開數據傾斜的優化之前,需要先了解 Hive 所采用 MapReduce 的原理

以上圖為例,快速過一遍 MapReduce 的工作流程:

1、首先把需要處理的數據文件上傳到 HDFS 上,然后這些數據會被分為好多個小的分片,然后每個分片對應一個 map 任務,推薦情況下分片的大小等于 block 塊的大小。然后 map 的計算結果會暫存到一個內存緩沖區內,該緩沖區默認為 100M,等緩存的數據達到一個閾值的時候,默認情況下是 80%,然后會在磁盤創建一個文件,開始向文件里邊寫入數據。
2、map 任務的輸入數據的格式是 key-value 對的形式,然后 map 在往內存緩沖區里寫入數據的時候會根據 key 進行排序,同樣溢寫到磁盤的文件里的數據也是排好序的,最后 map 任務結束的時候可能會產生多個數據文件,然后把這些數據文件再根據歸并排序合并成一個大的文件。
3、然后每個分片都會經過 map 任務后產生一個排好序的文件,同樣文件的格式也是 key-value 對的形式,然后通過對 key 進行 hash 的方式把數據分配到不同的 reduce 里邊去,這樣對每個分片的數據進行 hash,再把每個分片分配過來的數據進行合并,合并過程中也是不斷進行排序的。最后數據經過 reduce 任務的處理就產生了最后的輸出。

簡單來說,map 階段負責不同節點上一部分數據的統計工作,reduce 階段負責匯總聚合的工作。

有時一個 reduce 可以處理多個任務,但一些全局的工作只能讓一個 reduce 負責,例如統計總行數、distinct去重等,此時就 reduce 就不能有多個實例并發執行,這就會造成其他 reduce 的任務已經執行完了,而負責全局的 reduce 還沒執行完,這就是數據傾斜的本質,因此避免數據傾斜的核心在于均勻分配任務。

1、數據量大的時候用group by

當需要對數據進行去重時,在數據量較大的情況下可以選擇用 group by 而不是 distinct,原理如下:

默認情況下,map 階段同一 key 數據分發給一個 reduce,當一個 key 數據過大時就會發生數據傾斜了。但是并不是所有的聚合操作都只能在 reduce 完成,很多聚合操作也可以先在 map 進行部分聚合,最后在 reduce 端得出最終結果。

開啟 Map 端聚合參數設置

(1)是否在 Map 端進行聚合,默認為 true

set hive.map.aggr = true;

(2)在 Map 端進行聚合操作的條目數目

set hive.groupby.mapaggr.checkinterval = 100000;

(3)有數據傾斜的時候進行負載均衡(默認是false)

set hive.groupby.skewindata = true;

當選項設定為 true,生成的查詢計劃會有兩個MR Job。第一個MR Job中,Map 的輸出結果會隨機分布到 Reduce 中,每個 Reduce 做部分聚合操作,并輸出結果,這樣處理的結果是相同的 Group By Key 有可能被分發到不同的 Reduce 中,從而達到負載均衡的目的;第二個MR Job再根據預處理的數據結果按照 Group By Key 分布到 Reduce 中(這個過程可以保證相同的Group By Key被分布到同一個Reduce中),最后完成最終的聚合操作。

而與之相對應的,distinct 則只會用一個 reduce 來執行,造成數據量過大而讓整體任務執行時間過長或無法完成。

但是需要注意的是,用 group by 來去重會額外增加一個子查詢,只有當數據量很大的情況或任務執行中出現嚴重的數據傾斜,group by 去重后 count 才會比 count(distinct) 效率更高。

2、Mapjoin

如果不指定 MapJoin 或者不符合 MapJoin 的條件,那么 Hive 解析器會將 Join 操作轉換成 Common Join,即:在 Reduce 階段完成 join。容易發生數據傾斜。可以用 MapJoin 把小表全部加載到內存在 map 端進行 join,避免 reducer 處理。

(1)設置自動選擇 Mapjoin

set hive.auto.convert.join = true; 默認為true

(2)大表小表的閾值設置(默認25M以下認為是小表):

set hive.mapjoin.smalltable.filesize=25000000;

數據傾斜的處理在 Hive 優化中是一個大課題,實際場景中所遇到的 Hive 任務執行過長或報錯有80%都與數據傾斜有關,后續有機會的話可能專門寫一篇針對解決數據傾斜的文章。

三、參數優化

該部分羅列了一些常用的 Hive 參數設置,并逐條做簡單介紹

1、set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveFormat;(默認開啟)

將多個小文件打包作為一個整體的 inputsplit,減少 map 任務數

2、set hive.merge.mapfiles=true;(默認值為真)

合并 map 端小文件的輸出

3、set hive.auto.convert.join=true;

開啟 mapjoin

4、set hive.mapjoin.smalltable.filesize=25000000; (默認25M)

設置 mapjoin 的開啟閾值

5、set hive.optimize.skewjoin=true;

有數據傾斜的時候進行負載均衡

6、set hive.skewjoin.key=100000;

表示當記錄條數超過100000時采用 skewjoin 操作

7、set hive.exec.parallel=true;

多個 join 多個 union all 優化,開啟不同 stage 任務并行計算

8、set hive.exec.parallel.thread.number=16;(默認為8)

同一個 SQL 允許最大并行度

9、set hive.map.aggr=true;

group by 數據傾斜優化 設置在 map 端進行聚合

10、set hive.groupby.skewindata=true;

group by 數據傾斜優化

11、set hive.exec.mode.local.auto=true;

開啟本地模式

12、set mapred.compress.map.output=true;

開啟中間壓縮

以上是 Hive 通用屬性的設置,下面的參數主要目的是控制 map 和 reduce 的數量,需要依情況而設定:

13、set hive.merge.smallfiles.avgsize=16000000;

平均文件大小,是決定是否執行合并操作的閾值

14、set mapred.min.split.size.per.node=128000000;

低于 128M 就算小文件,數據在一個節點會合并,在多個不同的節點會把數據抓取過來進行合并

15、set mapred.min.split.size.per.rack=64000000;

每個機架處理的最小 split

16、set mapred.max.split.size=256000000;

決定每個 map 處理的最大的文件大小

17、set mapred.min.split.size=10000000;

決定每個 map 處理的最小的文件大小

18、set hive.merge.size.per.task=256000000;(默認值為256000000)

對 map 個數進行設置

19、set mapred.reduce.tasks=10;

設置 reduce 的數量

20、set hive.exec.reducers.bytes.per.reducer=536870912;(512M)

調整每個 reduce 處理數據量的大小

以上關于 map 和 reduce 的參數需要根據實際情況設置,具體的設置邏輯礙于篇幅所限就不展開了,如果有機會的話需要單獨列一篇作詳細介紹。

除了以上的優化方向外,還可以通過設置 Hive 的文件格式來提高效率,目前優化做得最好的文件格式就是 ORCfile,可以在建表時通過 stored as ORC 來調用。另外,可以根據實際工作需要把一些常用的統計匯總邏輯用中間表的形式存儲起來,便于后續查詢。

Hive 的優化是一個系統性的工作,本篇僅列一二,但是由于以后是 Spark 以及其他更優秀引擎的天下了,所以如果以后還要對 Hive 進行優化,那大概就是換一個語言吧(不是)。

如果覺得還有幫助的話,你的關注和轉發是對我最大的支持,O(∩_∩)O:

總結

以上是生活随笔為你收集整理的hive 两个没有null指定的表左关联的结果有null_Hive的优化原则的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。