大數(shù)據(jù)數(shù)倉的性能優(yōu)化主要圍繞以下四個(gè)方面:
- 調(diào)度優(yōu)化
- 模型優(yōu)化
- 同步任務(wù)優(yōu)化
- 計(jì)算任務(wù)優(yōu)化
下面將對著四方面的優(yōu)化方法進(jìn)行具體闡述。
調(diào)度優(yōu)化
在數(shù)據(jù)倉庫建設(shè)的過程中,我們不可避免的要執(zhí)行數(shù)據(jù)任務(wù),那么這些任務(wù)如何進(jìn)行配置才會是最優(yōu)的?如果任務(wù)調(diào)度配置存在問題,將會導(dǎo)致出現(xiàn)瓶頸任務(wù),或者無法及時(shí)提供業(yè)務(wù)所需的數(shù)據(jù),這時(shí)我們就需要首先從調(diào)度方面來考慮,是不是有些任務(wù)的調(diào)度時(shí)間設(shè)置不合理?或者是不是有的任務(wù)的優(yōu)先級設(shè)置不合理?
調(diào)度優(yōu)化方式
- 耗時(shí)長的任務(wù)定時(shí)時(shí)間提前
- 業(yè)務(wù)重要程度高的任務(wù)定時(shí)時(shí)間提前,并設(shè)置高優(yōu)先級,以便任務(wù)執(zhí)行時(shí)有更多資源
- 重要性低的任務(wù)避開調(diào)度高峰時(shí)間,以免發(fā)生搶資源,導(dǎo)致資源不足的情況
- 減少任務(wù)的依賴層級
模型優(yōu)化
對于數(shù)倉的建模而言,其實(shí)可以分為3NF建模和維度建模,推薦使用維度建模方式,可以按照星型模型或者雪花模型架構(gòu)的方式去建模。3NF建模方式或者實(shí)體建模方式的應(yīng)用性會差一點(diǎn),在很多時(shí)候其性能也會差一點(diǎn),但3NF會避免數(shù)據(jù)的冗余,其擴(kuò)展性會好一些。而維度建模會有一定的數(shù)據(jù)冗余,并且冗余程度會很高,但是對于上層使用者而言,其易用性要好很多,并且其查詢的性能也會好很多,雖然犧牲了一定的可擴(kuò)展性,但是仍然在可接受的范圍之內(nèi)。之所以在大數(shù)據(jù)的框架下推薦使用維度建模,是因?yàn)榻.a(chǎn)生的數(shù)據(jù)冗余對于大數(shù)據(jù)離線數(shù)倉來說,存儲的成本并不高,因?yàn)槠涠紝儆赟ATA盤的存儲,這樣的存儲成本是很低的。
總之,在大數(shù)據(jù)框架下推薦大家使用維度建模,使用星型模型或者雪花模型建模的方式,這樣無論對于后續(xù)的運(yùn)維還是后續(xù)的數(shù)據(jù)使用而言,都是比較便利的,并且性能會好一些。星型模型其實(shí)就是中間一個(gè)事實(shí)表,周邊圍繞著一堆維度表,其結(jié)構(gòu)會簡單一些,使用比較方便,性能也比較好;對于雪花模型而言,維度表可能還會繼續(xù)關(guān)聯(lián)其他的維度表,這種方式就是雪花模型,它會略微比星型模型復(fù)雜一些。其實(shí)星型模型也可以理解為較為簡單的雪花模型。這里推薦大家使用星型模型,當(dāng)然如果業(yè)務(wù)非常復(fù)雜,必須要使用雪花型也可以使用。這是因?yàn)樾切湍P碗m然有數(shù)據(jù)冗余,但是其結(jié)構(gòu)比較簡單,容易理解,而且使用起來只需要A傳給B就可以了,不需要再關(guān)聯(lián)一個(gè)C。
除了上述兩個(gè)較大的關(guān)鍵點(diǎn)之外,還有一些需要注意的小點(diǎn),比如中間表的使用。我們一般將數(shù)倉分為三層,第一層做緩沖,第二層做整合,第三層做應(yīng)用。但是并不是嚴(yán)格的只能分為三層,中間可能會有一些中間表,用于存儲中間計(jì)算的結(jié)果,如果能夠利用好中間表則會增強(qiáng)數(shù)倉的易用性和整體的性能。中間表的使用主要在數(shù)倉的第二層里面,因?yàn)樾枰蠑?shù)據(jù),但整合后的數(shù)據(jù)仍是明細(xì)數(shù)據(jù),對于這些表而言,數(shù)據(jù)量往往會比較大,而且會有見多的下游任務(wù)依賴這個(gè)表,因此可以做一些輕度的匯總,也就是做一些公共的匯總的中間表,這樣應(yīng)用層可以節(jié)省很多的計(jì)算量和成本。此外,雖然建議使用中間表,但也要注意中間表的數(shù)量,因?yàn)橹虚g表數(shù)量過多,就會有太多的依賴層級。
在某些業(yè)務(wù)場景下,我們還需要對寬表進(jìn)行拆表,拆表的情況一般發(fā)生在該表的字段較多,而其中幾個(gè)字段的產(chǎn)出時(shí)間較晚,導(dǎo)致整個(gè)表的交付時(shí)間也會延遲,在這種情況下我們可以將這幾個(gè)字段單獨(dú)拆出來處理,這樣就不會因?yàn)閹讉€(gè)字段影響其余業(yè)務(wù)的使用。
與拆表相對的情況是合表,隨著業(yè)務(wù)的增多,可能會有多個(gè)表中存放類似的數(shù)據(jù)指標(biāo),此時(shí),我們可以將多個(gè)表整合到一個(gè)表中,減少數(shù)據(jù)任務(wù)的冗余。
模型優(yōu)化--合理設(shè)計(jì)分區(qū)
表分區(qū)的功能一定要合理利用,這對于性能會產(chǎn)生很大的影響,一級分區(qū)一般都是按照天劃分的,建議大家一天一個(gè)增量或者一天一個(gè)全量來做。二級分區(qū)的選擇反而會多一些,首先大家要烤爐是否建立二級分區(qū),其次大家再選擇二級分區(qū)的建立方式。二級分區(qū)比較適合于在where語句中經(jīng)常使用到的字段,而且這個(gè)字段應(yīng)該是可枚舉的,比如部門名稱這樣的。這里還有一個(gè)前提,就是如果這個(gè)字段的值的分布是非常不均勻的,那么就不太建議做二級分區(qū)。
同步任務(wù)優(yōu)化
計(jì)算任務(wù)優(yōu)化
離線數(shù)倉的計(jì)算任務(wù)基本都是通過SQL實(shí)現(xiàn),這里也只講在SQL部分如何進(jìn)行優(yōu)化。我們平時(shí)在進(jìn)行數(shù)據(jù)處理,數(shù)據(jù)清洗,數(shù)據(jù)轉(zhuǎn)換,數(shù)據(jù)加工的過程中都會使用到SQL。對于大數(shù)據(jù)體系下的SQL的優(yōu)化而言,主要集中在兩個(gè)大的方面進(jìn)行:減少數(shù)據(jù)輸入和避免數(shù)據(jù)傾斜。減少數(shù)據(jù)輸入是最核心的一點(diǎn),如果數(shù)據(jù)輸入量太大,就會占用很多的計(jì)算資源。而數(shù)據(jù)傾斜是在離線數(shù)倉中經(jīng)常會遇到的,數(shù)據(jù)傾斜分為幾種,需要針對性的進(jìn)行優(yōu)化。
分區(qū)的合理使用
對有分區(qū)的表,合理使用分區(qū)可以過濾數(shù)據(jù),避免全表掃描,有效的降低計(jì)算的數(shù)據(jù)輸入。
一次輸入,多個(gè)輸出
SQL支持只讀取一次源數(shù)據(jù),然后將其寫入到多個(gè)目標(biāo)表,這樣就保證了只做一次查詢。語法如下
from (select user,seller from dwhtl.tmp_tab group by user,seller) a
insert overwrite table dwhtl.tmp_tab_1
select user,count(1)
group by user
insert overwrite table dwhtl.tmp_tab_2
select seller,count(1)
group by seller
先過濾數(shù)據(jù)再做計(jì)算
當(dāng)我們在使用join,Reduce或者UDF時(shí),先對數(shù)據(jù)進(jìn)行過濾也能有效的提高任務(wù)的效率
Map傾斜
當(dāng)發(fā)生數(shù)據(jù)再M(fèi)ap階段傾斜的情況,第一種處理方式反饋至業(yè)務(wù)層面,看能否通過業(yè)務(wù)層面的修改讓kv值均衡分布,如果業(yè)務(wù)層面無法處理,那么可以調(diào)整Map的個(gè)數(shù),也就是加大Map的計(jì)算節(jié)點(diǎn),默認(rèn)情況是每256M的數(shù)據(jù)為一個(gè)計(jì)算節(jié)點(diǎn),我們可以將其調(diào)小,也就是加大Map處理的節(jié)點(diǎn)的個(gè)數(shù),使得數(shù)據(jù)分割的更加均勻一些。
Join傾斜
Join階段的傾斜也是比較常見的,其解決方案需要分鐘如下幾種情況處理:
- 大表跟小表Join,則對小表加Map Join Hint
- 兩個(gè)大表Join,key值出現(xiàn)傾斜,如果傾斜值為Null,則需對Null值進(jìn)行隨機(jī)值處理
- 兩個(gè)大表Join,可以盡量先去重再Join
- 兩個(gè)大表Join,可以從業(yè)務(wù)層面考慮,檢查業(yè)務(wù)的必要性
Reduce傾斜
Reduce傾斜可能的情況有以下幾種:
- group by某個(gè)key傾斜嚴(yán)重
此時(shí)首先考慮該key是否可以過濾,如果不能,則可以改變寫法
select m.seller,sum(m.cnt)
from (select seller,count(1) cnt
from dwhtl.tmp_tab
group by seller,
if(seller='qaz',hash(rand())%10,0))m
group by m.seller
- distinct引起的數(shù)據(jù)傾斜
可以通過先打標(biāo)記,然后再group by的方式。如下的例子中就是對于求IP段,求美國IP段、中國IP段以及總的IP段一共有多少個(gè),左邊這種圖簡單的寫法,當(dāng)出現(xiàn)IP Key的傾斜就會使得作業(yè)比較慢,那么就可以將其打散,先求解這條ID的記錄是美國的還是中國的,在子查詢里先做這一步,在外面再去求解總的Count或者Sum,從原本Map-Reduce兩個(gè)階段的處理改成了Map-Reduce-Reduce三個(gè)階段處理,這種方案也能解決數(shù)據(jù)傾斜問題。
--可能會發(fā)生傾斜
select user,
count(distinct ip) ip_cnt,
count(distinct if(country='US',ip,null)) us_ip_cnt,
count(distinct if(country='CN',ip,null)) cn_ip_cnt
from tmp_tab
group by user
--改為如下寫法
select user,
count(1) ip_cnt,
sum(is_us) us_ip_cnt,
sum(is_cn) cn_ip_cnt
from (select user,ip,
if(country='US',1,0) is_us,
if(country='CN',1,0) is_cn
from tmp_tab
group by user,ip)a
group by user
總結(jié)一下,性能調(diào)優(yōu)歸根結(jié)底還是資源不夠了或者資源使用的不合理,或者是因?yàn)槿蝿?wù)分配的不好,使得某些資源分配和利用不合理。