Cuboid剪枝優化
爲什麼要進行Cuboid剪枝優化
將以減少Cuboid數量爲目的的Cuboid優化統稱爲Cuboid剪枝。在沒有采取任何優化措施的情況下,Kylin會對每一種維度的組合進行預計算,每種維度的組合的預計算結果被稱爲Cuboid。
- 如果有4個維度,可能最終會有2^4 =16個Cuboid需要計算。但在實際開發中,用戶的維度數量一般遠遠大於4個。
- 如果有10個維度,那麼沒有經過任何優化的Cube就會存在2^10 =1024個Cuboid
- 如果有20個維度,那麼Cube中總共會存在2^20 =104 8576個Cuboid
這樣的Cuboid的數量就足以讓人想象到這樣的Cube對構建引擎、存儲引擎壓力非常巨大。因此,在構建維度數量較多的Cube時,尤其要注意Cube的剪枝優化。
Cube的剪枝優化是一種試圖減少額外空間佔用的方法,這種方法的前提是不會明顯影響查詢時間。在做剪枝優化的時候,
- 需要選擇跳過那些“多餘”的Cuboid --》結合業務來判斷哪些cuboid是多餘
- 有的Cuboid因爲查詢樣式的原因永遠不會被查詢到,因此顯得多餘--》層級維度,省市區,年月日
- 有的Cuboid的能力和其他Cuboid接近,因此顯得多餘 --》衍生維度
檢查Cuboid數量
Apache Kylin提供了一個簡單的工具,檢查Cube中哪些Cuboid最終被預計算了,稱這些Cuboid爲被物化的Cuboid,該工具還能給出每個Cuboid所佔空間的估計值。由於該工具需要在對數據進行一定階段的處理之後才能估算Cuboid的大小,因此一般來說只能在Cube構建完畢之後再使用該工具。
使用如下的命令行工具去檢查這個Cube中的Cuboid狀態:
bin/kylin.sh org.apache.kylin.engine.mr.common.CubeStatsReader CUBE_NAME
# CUBE_NAME 想要查看的Cube的名字
示例:
bin/kylin.sh org.apache.kylin.engine.mr.common.CubeStatsReader cube_order
============================================================================
Statistics of cube_order[20191011000000_20191015000000]
Cube statistics hll precision: 14
Total cuboids: 3
Total estimated rows: 20
Total estimated size(MB): 1.02996826171875E-4
Sampling percentage: 100
Mapper overlap ratio: 0.0
Mapper number: 0
Length of dimension ITCAST_KYLIN_DW.FACT_ORDER.DT is 1
Length of dimension ITCAST_KYLIN_DW.FACT_ORDER.USER_ID is 1
|---- Cuboid 11, est row: 12, est MB: 0
|---- Cuboid 01, est row: 4, est MB: 0, shrink: 33.33%
|---- Cuboid 10, est row: 4, est MB: 0, shrink: 33.33%
----------------------------------------------------------------------------
輸出結果分析:
Cube statistics hll precision: 14
Total cuboids: 3
Total estimated rows: 20
Total estimated size(MB): 1.02996826171875E-4
Sampling percentage: 100
Mapper overlap ratio: 0.0
Mapper number: 0
- 估計Cuboid大小的精度(Hll Precision)
- 總共的Cuboid數量
- Segment的總行數估計
- Segment的大小估計,Segment的大小決定mapper、reducer的數量、數據分片數量等
|---- Cuboid 11, est row: 12, est MB: 0
|---- Cuboid 01, est row: 4, est MB: 0, shrink: 33.33%
|---- Cuboid 10, est row: 4, est MB: 0, shrink: 33.33%
- 所有的Cuboid及它的分析結果都以樹狀的形式打印了出來
- 在這棵樹中,每個節點代表一個Cuboid,每個Cuboid都由一連串1或0的數字組成
- 數字串的長度等於有效維度的數量,從左到右的每個數字依次代表Rowkeys設置中的各個維度。如果數字爲0,則代表這個Cuboid中不存在相應的維度;如果數字爲1,則代表這個Cuboid中存在相應的維度
- 除了最頂端的Cuboid之外,每個Cuboid都有一個父親Cuboid,且都比父親Cuboid少了一個“1”。其意義是這個Cuboid就是由它的父親節點減少一個維度聚合而來的(上卷)
- 最頂端的Cuboid稱爲Base Cuboid,它直接由源數據計算而來。Base Cuboid中包含所有的維度,因此它的數字串中所有的數字均爲1
- 每行Cuboid的輸出中除了0和1的數字串以外,後面還有每個Cuboid的具體信息,包括該Cuboid行數的估計值、該Cuboid大小的估計值,以及這個Cuboid的行數與父親節點的對比(Shrink值)
- 所有Cuboid行數的估計值之和應該等於Segment的行數估計值,所有Cuboid的大小估計值應該等於該Segment的大小估計值。每個Cuboid都是在它的父親節點的基礎上進一步聚合而成的
檢查Cube大小
在Web GUI的Model頁面選擇一個READY狀態的Cube,當我們把光標移到該Cube的Cube Size列時,Web GUI會提示Cube的源數據大小,以及當前Cube的大小除以源數據大小的比例,稱爲膨脹率(Expansion Rate)
一般來說,Cube的膨脹率應該在0%~1000%之間,如果一個Cube的膨脹率超過1000%,那麼應當開始挖掘其中的原因。通常,膨脹率高有以下幾個方面的原因:
- Cube中的維度數量較多,且沒有進行很好的Cuboid剪枝優化,導致Cuboid數量極多
- Cube中存在較高基數的維度,導致包含這類維度的每一個Cuboid佔用的空間都很大,這些Cuboid累積造成整體Cube體積變大
- 存在比較佔用空間的度量,例如Count Distinct,因此需要在Cuboid的每一行中都爲其保存一個較大度量數據,最壞的情況將會導致Cuboid中每一行都有數十KB,從而造成整個Cube的體積變大。
對於Cube膨脹率居高不下的情況,管理員需要結合實際數據進行分析,優化。
使用衍生維度
使用衍生維度用於在有效維度內將維度表上的非主鍵維度排除掉,並使用維度表的主鍵(其實是事實表上相應的外鍵)來替代它們。
創建Cube的時候,這些維度如果指定爲衍生維度,Kylin將會排除這些維度,而是使用維度表的主鍵來代替它們創建Cuboid。後續查詢的時候,再基於主鍵的聚合結果,再進行一次聚合。
優化效果:維度表的N個維度組合成的cuboid個數會從2的N次方降爲2。
不適用的場景:
- 如果從維度表主鍵到某個維度表維度所需要的聚合工作量非常大,此時作爲一個普通的維度聚合更合適,否則會影響Kylin的查詢性能
聚合組