前面說過構建一個n維的cube有多少種情況了,2^n-1種。構建一個10維的是1023種情況,一個20維的是1048576。那如果有30維甚至100維的了?這對於集羣來說壓力非常大,所以我們應該想想到底有沒有必要構建這麼多種情況了。
舉個例子,年,月,日三個字段總共可以構建7種可能。但是年,日構建起來有必要嗎?單獨一個日構建有必要嗎?真正有價值的組合是 年月日、年月、年,這3種可能。計算的可能性直接從7變爲3,是不是節省了很多時間。
所以我們有必要對我們構建的cube進行優化。
1.使用衍生維度。
衍生維度用於在有效維度內將維度表上的非主鍵維度排除掉,並使用維度表的主鍵(其實是事實表上相應的外鍵)來替代它們。Kylin會在底層記錄維度表主鍵與維度表其他維度之間的映射關係,以便在查詢時能夠動態地將維度表的主鍵“翻譯”成這些非主鍵維度,並進行實時聚合。
舉個例子,還是以員工表和部門表舉例,如下job來自員工表,dname是員工表和部門表都有的,local是部門表的,sal爲度量,構建一個三維的表,下面給了4條數據。
job dname local sal
1 111 a 10000
2 222 b 20000
3 333 c 30000
4 444 a 20000
本來總共有7中情況要構建,但是我覺得job和local之間有某種關係。所以我將local這個維度設成衍生變量,並保存job和lcal之間的映射關係。這樣我只用構建job,dname這兩個維度,總共就只有3種情況了(job,dname,job_dname)。表變成如下:
job dname sal
1 111 10000
2 222 20000
3 333 30000
4 444 20000
那如果我想通過local求sum(sal)該怎麼做了?先找到job和sal的關係,然後通過job和local之間的映射轉化成local和sal的關係,再求和。
job sal local sal
1 10000 a 10000
2 20000 =====》 b 20000
3 30000 c 30000
4 20000 a 20000
但是我們發現,job和sal轉化爲local和sal之後不一定是最終的結果,比如有兩條數據local都是a,還要再聚合一次,local和sal的最終結果如下。
local sal
a 30000
b 20000
c 30000
所以這裏你就發現了衍生維度的好處和壞處了吧,好處是構建cube的情況變少了(最終的數據量少,佔用空間少),壞處就是實時查詢的時候還要做聚合操作(多花費一些時間),以空間換時間,所以到底用不用衍生維度只能權衡。如果最終某個維度要聚合的數據量很大,那還是不要把這個維度設成衍生維度了。
衍生維度設置如下,將你需要的維度選擇derived,而不是normal。
設置完成後我們看看cube和以前有哪些不同,查看cuboid發現只有15個了,說明衍生維度生效了。
2.使用聚合組
聚合組可以把我們的所有維度情況分爲幾個組,比如最開始舉例的年月日。只可能有3種情況(年,年月,年月日),我們發現年是肯定有的,那我們是不是隻需要計算和年有關的情況就行了,其他情況忽略掉就可以了。
有3種方法給我們來分組。
1.強制維度。
把A設成強制維度,所有情況中必須包換A。年月日的例子用年作爲強制維度是不是就可以少計算幾種情況。
2.層級維度
使用A->B作爲層級維度,不可能出現以B開頭的可能。
3.聯合維度
使用AB作爲聯合維度,結果中有A,B的,必須同時包含AB。
聚合維度的設置在如下圖所示位置:
3.RowKey優化
這裏的rowkey就是hbase的rowkey,Kylin會把所有的維度按照順序組合成一個完整的Rowkey,並且按照這個Rowkey升序排列Cuboid中所有的行。設計良好的Rowkey將更有效地完成數據的查詢過濾和定位,減少IO次數,提高查詢速度,維度在rowkey中的次序,對查詢性能有顯著的影響。
1.被用作where過濾條件的維度放在前面。
考慮如上的sql情況,左邊的hbase表需要掃描3次位置,右邊的表只需要掃描一次。(hbase以字典排序,當然上面3個字段存在hbase裏面組合起來是一個rowkey)
2.把基數大的維度放在基數小的維度前面。
基數的意思就是維度去重後的個數,比如月維度去重後是12,日去重後是31,所以日維度放在月維度前面。
以上圖說明這樣做的好處,一開始的四維1111分解爲三維的時候有四種情況,這裏列出兩種情況1110和1101。當分解爲二維的情況1100的時候,這個二維的1100的數據既可以從三維1110取也可以從三維1101取。Kylin內部的機制是從id小的取,也就是從1101取。1101的D有3條數據,而1110的C有6條數據。所以從1101取數據聚合的數據量更小,效率更好。爲什麼C的數據量比D大了?這就是因爲我們一開始對四維的維度排序的時候是按照基數大小ABCD排序的,而不是按照ABDC來排序的。
rowkey設置在如圖所示位置:
4.併發粒度優化
當Segment中某一個Cuboid的大小超出一定的閾值時,系統會將該Cuboid的數據分片到多個分區中,以實現Cuboid數據讀取的並行化,從而優化Cube的查詢速度。具體的實現方式如下:構建引擎根據Segment估計的大小,以及參數“kylin.hbase.region.cut”的設置決定Segment在存儲引擎中總共需要幾個分區來存儲,如果存儲引擎是HBase,那麼分區的數量就對應於HBase中的Region數量。kylin.hbase.region.cut的默認值是5.0,單位是GB,也就是說對於一個大小估計是50GB的Segment,構建引擎會給它分配10個分區。用戶還可以通過設置kylin.hbase.region.count.min(默認爲1)和kylin.hbase.region.count.max(默認爲500)兩個配置來決定每個Segment最少或最多被劃分成多少個分區。由於每個Cube的併發粒度控制不盡相同,因此建議在Cube Designer 的Configuration Overwrites中爲每個Cube量身定製控制併發粒度的參數。
併發粒度優化在如圖所示位置: