摘要:?對于阿里云大數據數倉建設性能優化而言,主要可以從調度優化、模型優化、同步優化以及任務優化這四個方面著手。其實,對于性能優化而言,最終還是會歸結到“資源”之上,所以資源是否足夠,分配是否合理也是我們在進行性能優化時必須考慮的關鍵所在。
摘要:對于阿里云大數據數倉建設性能優化而言,主要可以從調度優化、模型優化、同步優化以及任務優化這四個方面著手。其實,對于性能優化而言,最終還是會歸結到“資源”之上,所以資源是否足夠,分配是否合理也是我們在進行性能優化時必須考慮的關鍵所在。
以下內容根據演講視頻以及PPT整理而成。
本次演講視頻分享,請戳這里!
本次演講PPT下載,請戳這里!
關于MaxCompute更多精彩文章,請移步云棲社區MaxCompute公眾號!
本文將主要圍繞以下四個方面進行介紹:調度優化、模型優化、同步優化以及任務優化。對于調度優化而言,將分享任務調度如何進行優化,以及如何看到調度的瓶頸點,以及在初步進行建設和使用數據倉庫的任務之后,對于任務如何進行調整來滿足業務的時間要求。對于模型優化而言,主要包括一些優化相關的想法、建議以及技術的優化點。對于數據同步優化而言,也是大家在建設數據倉庫的過程中經常遇到的問題,也就是將數據從其他數據庫同步過來或者向其他數據庫進行數據同步的時候,經常會遇到一些像某些任務運行過慢或者影響其他任務的情況。對于任務優化而言,主要指的是計算任務,也可以理解為MaxCompute的SQL任務,這部分將與大家分享如何去優化這部分的任務。
一、調度優化
在數據倉庫建設的過程中,大家都會需要跑一些任務,那么這些任務如何進行配置才會是最優的呢?如果出現了瓶頸點或者業務第二天所需要的數據并沒有給到,那么很大一部分的情況需要從調度方面來考慮,是不是有些任務的時間點設置的不合理?或者是不是有些任務的優先級設置的不合理?這些可能是在調度層面,大家需要優先考慮的一個點。
調度優化方式
調度優化的主要方式如下圖所示,按照道理前三點應該在設計初期提前想到或者提前規劃好的。而目前大部分客戶還是用了一段時間的數據倉庫的時候,才發現存在一些問題,當第二天需要出報表的時候才想到去優化這些點。
第一點就是對于大任務而言,需要將其預定處理的時間提前,這里的大任務也就是耗時比較長的任務,如果任務已經在跑了,那么很好評估,在DataWorks里面可以看到哪些任務跑得慢。此外還有一個評估方法就是在第一次建立數倉的時候,表的數據量很大那么也肯定是大任務。對于這些大任務而言,需要將其定時的時間提前,也就是將其優先級提前。第二點就是將關鍵節點的定時時間提前,這里所謂的關鍵節點并不是說其數據量大,而是業務很重要的任務。第三點就是需要做到任務的隔離,這里主要指的是在使用DataWorks的時候會用到一些調度資源,不管是運行SQL也好還是運行同步任務也好,這些任務都需要跑在DataWorks的調度資源里面,那么如果將這些任務都放在一個項目就會出現問題,比如某個同步任務設置了10個并發,這樣就占據了10多個調度資源,這樣就可能將資源全部占滿了,這樣就會導致其他任務需要等待,這里不是指的MaxCompute資源不夠,而是DataWorks的調度資源不夠了。因此,一方面需要將開發和生產隔離開,避免因為開發臨時啟動了測試任務導致生產環境受到影響,因此要盡量將DataWorks里面的開發項目和生產項目分離開。此外,如果生產項目也很大,可能就需要按照數倉的分層或者不同業務拆分成不同的項目,這也是避免資源出現搶占,避免影響其他業務的一種方式。當然,這樣的做法有利也有弊,因為這樣做會使得復雜度增加,對于企業而言,后續的運維成本也會高一些,因此這需要看大家應該如何評估,如果數據量達到了一定的規模其實可以分拆出來的,但是如果數據量不是很大,那么就可以先不考慮分拆。第四點就是減少任務層級的依賴,大家在進行調度的時候,都會在DataWorks里面看到依賴的上一層或者下游依賴哪一些任務,而任務互相依賴的層級應該是越少越好的,但是按照數倉分層,依賴至少需要三層,這三層依賴是肯定存在的,除此之外還會有一些中間表,這樣就會有四層或者五層,但是盡量不要出現10層以上甚至20層的依賴,這樣復雜的任務依賴會使得后期去排查任務的依賴成本升高。如果在數倉建設的初期或者建設的過程中發現了一些問題就可以從以上四個點出發進行考慮。
二、模型優化
對于模型優化而言,必須要按照什么方式進行設計以及模型必須是什么樣子的,其實沒有一個定性的結論。這里也只是給出一些建議和想法。
對于數倉的建模而言,其實可以分為3NF建模和維度建模等,而推薦使用維度建模方式,可以按照星型模型或者雪花型架構的方式去建模。3NF建模方式或者實體建模方式的應用型會差一點,在很多時候其性能也會差一點,但是3NF在很多時候都會避免數據的冗余,其擴展性會好一些。而維度建模會有一定的數據冗余,并且冗余程度會很高,但是對于上層使用者而言,其易用性要好很多,并且其查詢的性能也會好很多,雖然可擴展性會稍微差一些,但是仍然處于可接受的范圍之內。之所以在MaxCompute這邊推薦大家使用維度建模,是因為其特點之一就是會存在數據冗余,但是數據冗余對于MaxCompute這種離線數據倉庫來說,存儲成本并不是很高,因為其都屬于SATA盤的存儲,這樣的存儲成本是很低的,而傳統的數據倉庫比如使用Oracle等其他的關系型數據庫構建的數據倉庫,大家往往會選擇3NF的建模方式,這是因為其數據冗余存儲成本會很高,磁盤很貴。
總之,在MaxCompute上推薦大家使用維度建模,使用星型建模或者雪花型建模的方式,這無論對于后續的運維還是后續對于數據的使用而言,都是比較便利的,并且性能也會好一些。星型模型其實就是中間一個事實表,周邊圍繞著一堆維度表,其結構會簡單一些,使用比較方便,性能也比較好;對于雪花模型而言,維度表可能還會繼續關聯其他的維度表,這種方式就是雪花模型,它會略微比星型模型復雜一些。其實星型模型也可以理解為較為簡單的雪花模型。這里推薦大家使用星型模型,當然如果業務非常復雜,必須要使用雪花型也可以使用。這是因為星型模型雖然有數據冗余,但是其結構比較簡單,容易理解,而且使用起來只需要A傳給B就可以了,不需要再關聯一個C。
除了上述兩個較大的關鍵點之外,還有一些值得注意的小點,比如中間表的利用,在這部分主要是將數倉分為三層,第一層做緩沖,第二層做整合,第三層做應用。但是并不是嚴格地只能分為三層,中間還是會有一些中間表的,如果能夠利用好中間表則會增強數倉的易用性以及整體的性能。其主要是在數倉的第二層里面,因為需要整合一些數據,但是整合之后的數據依舊是明細的,可能有幾百億甚至幾千億的量級,對于這些表而言,數據量往往很大,而且下游任務以及依賴于這個表的報表任務有很多,因此可以做一些輕度的匯總,也就是做一些公共的匯總的中間表,這樣應用好了可以節省很多的計算量和成本的。雖然建議大家利用中間表,但是也不建議使用太多的中間表,這還是因為中間表越多,依賴的層級也會越多。
在某些情況下還需要進行拆表,比如某一個大表字段比較多,但是可能其中某兩三個字段的產出比較慢,產出很慢可能是因為其加工邏輯很復雜或者數據量比較大導致的,而其他字段產出卻是很快的,此時就可以將數據表拆開,將過慢的字段拆出來,并將原來正常的字段留在原來的表,這樣就可以避免因為兩個過慢的字段影響其他業務,拆表的場景雖然比較常見,但是可能不會在數倉建設初期就出現。
還有一種場景及就是合表,這與拆表是相對的,當大家使用數倉一段時間之后會發現A業務部門出了一些表,B業務部門也出了一些表,而這些表或者數據可能是重疊的,也可能業務含義是一樣的,只不過字段不一樣。對于這些表而言是可以進行合并的,因為在合并之后可以做整體批量加工的SQL,這樣要比多個表批量加工的SQL復雜度要低很多,而且性能要好很多。對于分區的場景而言,也要合理地設置MaxCompute的分區。
此外還有拉鏈算法,這在傳統數倉里面也會用到,大家往往會需要使用拉鏈算法來記錄歷史變化情況。而拉鏈算法會使得計算成本變得比較高,尤其在MaxCompute里面或者離線數倉Hive里面,這是因為其沒有Update的操作,因此需要遍歷全表,需要對比昨天的全量和今天的增量,甚至是比較昨天的全量和今天的全量,才能得到所想要的拉鏈算法的結果,這樣的計算成本對于MaxCompute而言要高很多。如果數據量不大,每天做全量的拉鏈算法也是沒有問題的,只需要考慮保留多久歷史數據的問題。而實際上,有些業務不會關心這些歷史數據的變化問題,對于這樣的業務其實可以只保留最近多少天的歷史數據就可以了。其實是因為MaxCompute這邊的數據存儲成本很低,如果不使用拉鏈算法,那么就意味著數據冗余會高很多,所以其實大家可以計算一下每天增量數據的存儲成本有多少,再對比一下數據的計算成本,根據自己的業務進行均衡。但是如果每天增量數據達到百億這種級別,保留全量數據肯定是不現實的,那么就還是去做拉鏈算法。
模型優化-合理設計分區
MaxCompute分區的功能一定要合理利用,這對于性能會產生很大的影響,一級分區一般都是按照天劃分的,建議大家一天一個增量或者一天一個全量來做。二級分區的選擇反而會多一些,首先大家可以選擇是否建立二級分區,其次大家可以選擇二級分區的建立方式。二級分區比較適合于在where語句中經常使用到的字段,而且這個字段應該是可枚舉的,比如“男”和“女”這樣的。這里還有一個前提,就是如果這個字段的值的分布是非常不均勻的,那么就不太建議做二級分區。
如下圖中的例子所示,登錄表每天會有9個億的數據,而其中的一個字段是“是否登錄成功”,成功可能有4億,失敗可能有5億,這就比較適合做二級分區,因為比較均衡。第二個例子是用戶訪問表,每天新增20億數據,其中一個字段是“頁面訪問狀態”,成功訪問“202”是18億,而失敗“203”只有0.5億,其他就更少了,這樣的字段就不適合做二級分區。在數量級不大的情況下,不建議做二級分區,因為幾百萬的數據在MaxCompute里面掃描起來也會很快,在數據量大了之后可以再考慮二級分區,因為MaxCompute本身對于分區有一個上限就是6萬,也就是一級分區乘以二級分區的個數不能超過6萬個。
三、同步任務優化
同步任務優化可以從下圖所示的這樣幾個點進行考慮。正如下面的這張PPT中圖所示。數據同步其實就是源庫通過網絡進入到DataWorks或者自定義的調度資源里,再從DataWorks里面同步到MaxCompute里面,或者反過來從MaxCompute同步到源庫,但是無論怎么說同步就是分為這樣的幾個點:源庫、網絡1、DataWorks調度資源、網絡2以及MaxCompute,出現瓶頸的地方也就在這幾部分中,如果同步任務運行緩慢,那么瓶頸點就只能出現在這幾個點中。最常見的情況就是從其他數據庫向MaxCompute抽取數據,一般情況下的瓶頸點就在源庫這部分,出現問題大家可以優先在源庫處尋找。在網絡層面,從DataWorks到MaxCompute之間的網絡2大家一般不用關心,因為這部分是由阿里云負責的,但是從源庫到DataWorks調度的網絡1這一段需要由用戶自己保證,公網、內網和專線,不同的網絡環境中同步的速度也是不一樣的。
再回到同步優化的幾個關鍵點,首先核心同步任務需要定時優先考慮,如果表的數據量比較大或者業務的優先級比較高,那么這些絕對需要提前考慮,因為如果這樣的任務不提前,那么排在其后面的任務就會受到影響。第二點就是網路對于同步性能的影響,公網、內網或者專線對于性能也會有一定的影響。第三點就是DataWorks調度資源對于同步任務的影響,大家在DataWorks里面進行同步都是使用默認的調度資源,如果同步任務設置的并發過高,就會導致某一個任務會影響其他任務,比如處理一百萬數據啟動了20個并發,顯然這是沒有必要的,但是這樣就占掉了全部的同步任務,導致后續運行SQL以及其他的同步任務都跑不起來了,這是因為DataWorks的調度資源不夠了。所以數據同步的并發絕對不是越多越好的,當處理一兩百萬數據的時候,僅需要2到3個并發就足夠了。此外,還有就是如何判斷源庫和目標庫哪個是瓶頸點。數據同步主要使用的是數據集成,當離線任務運行完成之后都會產生這樣的一個日志,在日志的最后會顯示開始時間、結束時間以及寫入速度等。在圖中有標紅的兩個點,分別是Task WaitWriterTime和Task WaitReaderTime。如果是從RDS往MaxCompute同步,那么Reader指的就是讀取RDS等待的時間,那Writer指的就是寫入MaxCompute的等待的時間,哪一邊的時間更長就意味著哪一邊存在瓶頸點,如果讀的方面時間更長,那么就需要從RDS或者網絡1入手,也就是通過兩方面的時間來判斷瓶頸點究竟在哪一部分。
計算任務優化
在計算任務優化部分部分,也只與大家分享在SQL部分開發者應該如何進行優化。大家平時在進行數據處理、數據清洗、數據轉換、數據加工等過程中都會使用到SQL。對于SQL的優化而言,主要集中在這樣的兩個大方面進行:減少數據輸入和避免數據傾斜。減少數據輸入是最核心的一點,如果數據輸入量太大,包括很多無效的數據,那么就會占用很多的計算資源。而數據傾斜是在離線的數倉里面經常會遇到的,幾乎每個人都會遇到,數據傾斜也分為好幾種,需要對應地進行優化。接下來就為大家展開進行論述。
在正式展開之前還需要講解一下LogView的用法,因為想要判斷問題究竟是因為什么導致都需要從分析LogView入手。每一個SQL執行的時候都會產生一個LogView,如下圖中的網址所示,大家可以直接在瀏覽器打開,之后就能打開匯總的頁面,再打開Detail就能看到如下圖所示的明細頁面。對于明細頁面而言,首先需要關注左側的執行計劃,也就是分為了多少個Map、Reduce以及Join節點。其次需要關注TimeLine可以看到哪一個Map運行的時間長,這是尋找數據傾斜的依據。當點擊每一個Map就能看到下面的明細,比如某一個Map有10個節點在跑,那么就會有10個點。對于明細而言,重點需要關注的也是TimeLine,需要關注在分成10個的節點里面,究竟哪一個跑得快,哪一個跑得慢。下圖中就存在明顯的傾斜,也就是0號節點跑得很慢,而其他的節點跑得就比較快,這樣就是一個非常明顯Map階段的傾斜。而使用Long-Task則可以快速定位到跑得慢的節點,幫助進行快速定位。
當然目前也有了比較好用的工具——MaxCompute Studio,其對于LogView的支持更加強大。在這里面可以直接將剛才的網址粘貼過來,也可以直接連接MaxCompute的項目找到Instance,然后直接點擊Instance查看其執行日志,甚至可以將LogView保存在本地或者在本地打開,而網頁版本過期之后就無法打開了。MaxCompute Studio最好用的地方在于其時序圖功能,時序圖能夠列出某一個時間段,哪一個節點跑得快,哪一個節點跑得慢,做一個整體地列舉出來,更加方便地定位到Map、Reduce以及里面小的節點。還有一個分析功能,能夠直接為用戶提供結果,提示用戶哪一個節點跑得慢,哪里出現長尾等問題。
分區的合理使用
前面講述了分區應該如何設計,這里著重講解分區應該如何使用。如果表存在一級分區,那么將分區的篩選放到了條件里面就是一種錯誤的寫法,有可能導致全表掃描。最好的寫法就是像下圖右側所示的一樣,把Table1的PT先進行篩選做一個子查詢,再把Table2的也做一個分區先篩選了作為t2,之后將它們兩個Join在一起再加上一個where條件,這樣就能避免全表掃描。對于PT而言,如果使用了系統自帶的函數,應該會做分區裁剪,而如果使用了自定義的函數對于PT進行加工,并放到了where條件里就有可能導致全表掃描,而現在DataWorks里面也會有系統提示,也便于大家進行判斷。
多路輸入
在MaxCompute里面支持多路輸入,可以讀取一個表的數據并將其同時寫入到兩個地方,這樣就保證了只做了一次查詢,而可以直接生成兩個結果表。下圖是一個電商的例子,大概就是在銷售訂單表里面有賣家和買家,分別統計了賣家和買家的數量分別是多少,以前可能需要拆分成兩個SQL,而現在可以用一個SQL同時統計兩者的數量,只需要讀取一次原表就可以了,既能夠節省時間,也能夠節省成本。
慎用SELECT*
因為MaxCompute里面是列式存儲,所以同一列的數據都是存儲在一起的,甚至于因為列內容相似都會有一些壓縮算法在里面。而SELECT*查詢全列與直接查詢兩個字段的性能差距是非常大的,所以作為數據開發的規范,無論數據量大小都一定不要使用SELECT*就好了。
先過濾JOIN,REDUCE,UDF
還有一個減少數據量的辦法就是在使用Join、Reduce或者UDF的時候,先做過濾在做具體的計算或者Join。
合表
合表也是減少數據輸入的一種方式,它其實是從業務的角度切入考慮的。比如有一個業務分別用到了T1和T2的兩列,另外一個業務分別用到了T1和T3的兩列,而這兩個業務其實是可以合并到一起的,但是卻放到了兩個表,而這樣就可以將這兩個表合并到一起,這樣只做一次計算就完成了。
Map傾斜
在LogView里面有一個Map的時序,可以看到每個Map里面有多少個Instance,里面的哪一個耗時比較長就是發生了數據傾斜。同樣的,在LogView里面也能找到Map的平均執行時間以及最大執行時間,如果兩者相差很大,那么必然出現了傾斜。對于這樣的問題,從業務層面進行解決一般是修改上游數據,讓上游按照均衡的KV值進行重新分布。如果業務層面無法規避,那么可以調整Map的個數,也就是加大Map的計算節點,在默認情況下是每256M數據切一個節點,可以將其調小,也就加大了Map處理節點的個數,使得數據分割得更加均勻一些。
Join傾斜
Join階段的傾斜也是比較常見的,這一現象的發現與Map傾斜基本相同,也是可以通過LogView判斷。但是其解決方案卻需要分為幾種情況進行處理:
-情況1:如果為大表與小表(加載到內存不超過512M),則對小表加MAPJOIN HINT
-情況2:兩個大表Join,KEY值出現數據傾斜,傾斜值為NULL,則需對NULL進行隨時值處理
-情況3:兩個大表Join,可以盡量先去重后再Join?? ?
-情況4:兩個大表Join,業務層面考慮優化,檢查業務的必要性
下圖展現的是Join傾斜的幾個具體例子,可以分析具體造成傾斜的情況做出相應的處理。
Reduce傾斜
Reduce傾斜現象的查看方式和前面的Map以及Join查看的方式相同,可以從TimeLine看到。可能的情況主要有以下四種:
-情況1:GROUP BY 某個KEY傾斜嚴重(1. 是否可以過濾 2. 寫法改變,見圖)
-情況2:DISTINCT引起的傾斜(打標+GROUPBY)?? ?
-情況3:動態分區引起的傾斜,盡量避免使用動態分區
-情況4:窗口函數引起的傾斜,盡量避免使用窗口函數,要視具體情況而定
Reduce傾斜-DISTINCT
如果是因為DISTINCT造成的數據傾斜,有一種解決方法就是打標+GROUPBY,比如在下圖的例子中就是對于求IP段,求美國IP段、中國IP段以及總的IP段一共有多少個,左邊這種圖簡單的寫法,當出現IP Key的傾斜就會使得作業比較慢,那么就可以將其打散,先求解這條ID的記錄是美國的還是中國的,在子查詢里先做這一步,在外面再去求解總的Count或者Sum,從原本Map-Reduce兩個階段的處理改成了Map-Reduce-Reduce三個階段處理,這種方案也能解決數據傾斜問題。
總結一下,性能調優歸根結底還是資源不夠了或者資源使用的不合理,或者是因為任務分配的不好,使得某些資源分配和利用不合理。大家需要根據本文的內容考慮如何將自己的任務打散,保證任務在規定的時間內能夠執行完畢,同時能夠保證成本的節約。當然了,大家不僅需要考慮MaxCompute的計算資源,也需要考慮DataWorks的調度資源,所以性能優化最終還是在和資源作斗爭,看資源是否足夠,分配是否合理。
本文為云棲社區原創內容,未經允許不得轉載。?
評論
查看更多