前端遍历导致查询数据时间过长_OLAP 服务器,空间换时间可行吗?
【摘要】
全量預匯總真的是提高 OLAP 性能的可行方案嗎?點擊了解OLAP 服務器,空間換時間可行嗎?
多維分析提供拖拽、旋轉、切片、鉆取等等人機交互操作,必須有秒級的響應速度。而這些操作對應的明細數據量非常巨大,如果在明細數據的基礎上直接計算,速度會很慢,等待時間過長,是用戶無法接受的。
圖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條少了很多。
如果再對比原始明細數據,當進行較長時間段統計的時候,計算量可以減少十倍甚至更多。
結論:部分預匯總可滿足多維分析性能要求,還能避免占用空間過大
經過“部分預匯總”優化后,我們雖然無法完全做到全量預匯總那樣直接查詢的程度,但常常也能把計算性能從全量硬遍歷提高幾十倍甚至上百倍,這對于大多數多維分析場景已經足夠了。
總結
以上是生活随笔為你收集整理的前端遍历导致查询数据时间过长_OLAP 服务器,空间换时间可行吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php 设置时区_为什么没有 Asia/
- 下一篇: python什么时候用类_python中