OLAP 伺服器,空間換時間可行嗎?

嘟嘟是隻喵發表於2020-11-30

多維分析提供拖拽、旋轉、切片、鑽取等等人機互動操作,必須有秒級的響應速度。而這些操作對應的明細資料量非常巨大,如果在明細資料的基礎上直接計算,速度會很慢,等待時間過長,是使用者無法接受的。

         ..

圖1:基於明細的OLAP響應時間過長

 

為了保證秒級甚至毫秒級的響應速度,一些OLAP產品事先將幾千萬甚至上億條明細資料計算成彙總資料,儲存在硬碟上。這樣,在分析的時候,就直接查詢彙總資料,不會出現等待時間過長的問題。這種預彙總的基本邏輯就是用更多的硬碟空間換更短的查詢時間。但是,容易忽視的一個問題是:到底要用多大的硬碟空間才能達到這個目的?下面就讓我們實際計算一下看看。

 

儲存空間計算1 :3 個獨立維度,7 箇中間結果…

為了簡化分析,我們假設一個多維分析系統,僅有3個獨立維度。獨立維度是指不相互依賴的維度,例如:產品(product)、僱員(employee)、客戶(customer)。類似“年/月/日”這樣的分層維度,可以認為是一個獨立維度,而不是多個。

這三個獨立維度組合預先彙總,會有7箇中間結果,也就是2的3次方減1個。如下:

1、  產品、僱員、客戶

2、  產品、僱員

3、  產品、客戶

4、  產品

5、  僱員、客戶

6、  僱員

7、  客戶

 

儲存空間計算2 :50 個獨立維度,要一百萬塊硬碟!

一般的多維分析系統都不會只有3個獨立維度,假設有50個的話,我們將所有可能的維度組合都預先彙總出來存在硬碟上,會有多少箇中間結果呢?答案是2的50次方減1個!

這些中間結果我們稱之為中間CUBE(立方體)。每個中間CUBE還會包含很多彙總資料,。例如:“2、產品、僱員”這個中間結果就包括很多行產品、僱員組合起來的彙總訂單金額值。假設每個中間CUBE有1K位元組資料,那麼2的50次方箇中間CUBE佔用的儲存空間將超過1MT。也就是說,需要一百萬個1T的硬碟才能存的下!

 

儲存空間計算3 :50 個獨立維度選20 個分析,還要幾十萬塊硬碟!

根據實際情況,一般使用者都不會選中所有的50個維度來做分析,沒必要預彙總所有的維度組合。所以我們減少維度個數,最多隻彙總50個維度中的20個。在數學上,從50個維度中選出n個,用組合數C(50,n)來表示。所以從50個維度中選出1到20個維度形成的中間結果就有C(50,1)+C(50,2)+…+C(50,20)。我們只看這裡面最大的一個C(50,20),含義是從50個維度中選出20個來彙總成中間結果,得到的中間CUBE大概是4.7E13個,也就是4.7乘以10的13次方個。這些中間結果都包含20個獨立維度,所以包含的彙總資料的數量比較大,我們保守估計每個有1萬行,總共就有4.7E17行資料(4.7E13乘以1萬)。即使不考慮維度欄位,只考慮一個彙總欄位“訂單金額”,僅佔用1位元組儲存,計算出來也需要470000T以上的容量,還是需要47萬塊硬碟!

 

儲存空間計算4 :6 層交叉表,4 個切片維度,仍然要上千塊硬碟!

繼續從實用角度出發,多維分析一般展現為多層表頭的交叉表。例如:2層上表頭是客戶和產品維度,1層左表頭是僱員維度。表頭層數太多時,分析起來也很不方便。我們就假設上表頭和左表頭都是3層,也就是總共6層。50個維度中取6個的組合數為C(50,6),大概是1589萬個組合。仍然按照每個中間CUBE有1萬行計算,總行數不到160G行。每行資料只算十幾個統計值,一般不會超過1K,那麼總共需要100T儲存容量。也就是100塊硬碟就夠了,看起來似乎可以接受。

但是,多維分析不能只看交叉表,還要做一些切片條件過濾操作。例如:針對某個僱員、某個客戶、某個產品來看看其他維度的交叉表。所以,與彙總的資料,不能只考慮交叉表本身的6維度,還要加上切片用到的維度。假設再留4個維度來切片,就要計算10個維度需要的空間了。C(50,10)大概是100億個中間CUBE,每個按照1萬行,總計就是100T行。每行十幾個統計值,1K容量,總容量又是幾千T了,還是需要上千硬碟。

 

問題出在哪裡?全量預彙總不可行,要部分預彙總。

上面計算的全量預彙總的優點是將需要的統計結果全部計算出來,分析的時候直接用就可以了,不用再做任何彙總。但是,經過上面的計算我們發現,全量預彙總需要的硬碟數量太多,已經不可行了。

所以,我們要改變一下思路,不把每種可能出現的維度組合都預彙總出來,只預彙總部分維度組合。在查詢時,對於已經有預彙總的資料則直接返回,而如果碰到沒有預彙總的維度組合時,則仍然從原始明細資料遍歷聚合出來。

更進一步,我們還可以從某個已有的中間 CUBE 聚合。比如,如果儲存了維度組合 [A,B,C] 的預彙總資料,那麼維度組合 [A,B] 或[B,C]的查詢就可以從這個中間 CUBE 再聚合出來了,而不必從原始明細資料聚合,計算量將會大大降低。為了容易理解,我們用SPL語言來舉例說明如何實現部分預彙總,如下圖:

..

圖2:部分預彙總

圖2中,訂單明細預先按照日期和部門彙總儲存成中間CUBE,資料量就小了很多。再按照②③④三種方式彙總時,就可以在中間CUBE基礎上再次彙總了。這樣做,即解決了在大量明細資料上彙總耗時太長的問題,也避免了全量預彙總佔用空間過大的問題。

有時可能會有多箇中間 CUBE 都能聚合出目標查詢,比如組合 [A,B,C] 和[B,C,D]都可以再聚合出組合[B,C],這時SPL會優先選擇資料量較小的那個中間 CUBE,保證獲得最好效能 。

那麼,我們怎麼知道在初始狀態時該預先彙總哪些組合呢?

可以動態生成這些組合。在查詢時,無法從現有中間 CUBE 聚合出來的組合只能從原始明細資料聚合,我們可以在聚合完成後將結果儲存起來作為一個新的中間 CUBE。發現新組合時第一次訪問會有延遲感,以後基於這個組合的查詢或者可由該組合聚合出來的查詢就都可以較快返回了。

其實,也不是隻要能從現有中間 CUBE 聚合出來的組合就總是臨時聚合。多維分析效能優化的目標是前端反應速度,如果中間 CUBE 仍然很大,那麼再聚合也會比較慢,這時候,這些再聚合的結果也可以作為一些新的中間 CUBE 儲存起來。

另外,在過程中我們還可以記錄每個中間 CUBE 的使用頻率,在空間總量限制下,刪除那些使用率較低的中間 CUBE,從而更有效地利用有限的空間。

 

還可以利用的技巧:時間段預彙總

很多場景下,明細資料都是按照日期順序儲存的,我們可以將資料按更高的時間維度層次預彙總,在查詢時就可以減少遍歷計算量。如下圖計算20180609到20181111的銷售總金額:

..

圖3:時間段預彙總

為了方便理解,圖3中用按照日期彙總資料來代替原始明細檔案,實際上用明細檔案也是一樣的原理。從20180609到20181111是145天,如果直接用按照日期彙總資料來計算需求的話,要彙總145條資料。

如果我們事先有月彙總資料(圖3右上程式碼準備),那麼可以利用它來減少計算量。SPL在計算從20180609到20181111這段日期的統計時,會將日期段劃分為3段:6月19日-6月30日,需要查詢12條日金額資料。7月-10月是整月彙總,只需要查詢4條月金額資料就可以了。11月1日-11月11日,11條日金額資料。3段彙總資料共27條,比直接查日彙總資料145條少了很多。

如果再對比原始明細資料,當進行較長時間段統計的時候,計算量可以減少十倍甚至更多。

 

結論:部分預彙總可滿足多維分析效能要求,還能避免佔用空間過大

經過“部分預彙總”優化後,我們雖然無法完全做到全量預彙總那樣直接查詢的程度,但常常也能把計算效能從全量硬遍歷提高几十倍甚至上百倍,這對於大多數多維分析場景已經足夠了。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31543054/viewspace-2738057/,如需轉載,請註明出處,否則將追究法律責任。

相關文章