目錄
一、Kylin增量構建
1、應用場景
Kylin在每次Cube的構建都會從Hive中批量讀取數據,而對於大多數業務場景來說,Hive中的數據處於不斷增長的狀態。爲了支持Cube中的數據能夠不斷地得到更新,且無需重複地爲已經處理過的歷史數據構建Cube,因此對於Cube引入了
增量構建
的功能
2、理解Cube、Cuboid與Segment的關係
-
Kylin將Cube劃分爲多個Segment(對應就是HBase中的一個表),每個Segment用起始時間和結束時間來標識。
-
Segment代表一段時間內源數據的預計算結果。
-
一個Segment的起始時間等於它之前那個Segment的結束時間,同理,它的結束時間等於它後面那個Segment的起始時間。
-
同一個Cube下不同的Segment除了背後的源數據不同之外,其他如結構定義、構建過程、優化方法、存儲方式等都完全相同。
一個Cube,可以包含多個Cuboid,而Segment是指定時間範圍的Cube,可以理解爲Cube的分區。對應就是HBase中的一張表。該表中包含了所有的Cuboid。
例如:以下爲針對某個Cube的Segment
3、全量構建與增量構建
全量構建
在全量構建中,Cube中只存在唯一的一個Segment,該Segment沒有分割時間的概念,也就沒有起始時間和結束時間。
全量構建和增量構建各有其適用的場景,用戶可以根據自己的業務場景靈活地進行切換。
對於全量構建來說,每當需要更新Cube數據的時候,它不會區分歷史數據和新加入的數據,也就是說,在構建的時候會導入並處理所有的原始數據。
增量構建
增量構建只會導入新Segment指定的時間區間內的原始數據,並只對這部分原始數據進行預計算。
全量構建和增量構建的對比
全量構建Cube全量構建與增量構建的Cube查詢方式對比:
-
-
查詢引擎只需向存儲引擎訪問單個Segment所對應的數據,無需進行Segment之間的聚合
-
爲了加強性能,單個Segment的數據也有可能被分片存儲到引擎的多個分區上,查詢引擎可能仍然需要對單個Segment不同分區的數據做進一步的聚合
-
-
增量構建Cube
-
由於不同時間的數據分佈在不同的Segment之中,查詢引擎需要向存儲引擎請求讀取各個Segment的數據
-
增量構建的Cube上的查詢會比全量構建的做更多的運行時聚合,通常來說增量構建的Cube上的查詢會比全量構建的Cube上的查詢要慢一些
-
對於小數據量的Cube,或者經常需要全表更新的Cube,使用全量構建需要更少的運維精力,以少量的重複計算降低生產環境中的維護複雜度。而對於大數據量的Cube,例如,對於一個包含兩年曆史數據的Cube,如果需要每天更新,那麼每天爲了新數據而去重複計算過去兩年的數據就會變得非常浪費,在這種情況下需要考慮使用增量構建
4、增量構建Cube過程
1、指定分割時間列
增量構建Cube的定義必須包含一個時間維度,用來分割不同的Segment,這樣的維度稱爲分割時間列(Partition Date Column)。
2、增量構建過程
-
在進行增量構建時,將增量部分的起始時間和結束時間作爲增量構建請求的一部分提交給Kylin的任務引擎
-
任務引擎會根據起始時間和結束時間從Hive中抽取相應時間的數據,並對這部分數據做預計算處理
-
將預計算的結果封裝成爲一個新的Segment,並將相應的信息保存到元數據和存儲引擎中。一般來說,增量部分的起始時間等於Cube中最後一個Segment的結束時間。
5、增量Cube的創建-案例
準備動作
1.執行建表語句
-- 1. 創建數據庫、創建表
create database if not exists `kylin_dw`;
-- 2. 創建用戶維度表
create table `kylin_dw`.`dim_user`(
id string,
name string
)
row format delimited fields terminated by ',';
-- 3. 創建訂單事實表
create table `kylin_dw`.`fact_order`(
order_id string,
user_id string,
price int
)
partitioned by (dt string)
row format delimited fields terminated by ',';
2.導入數據
load data local inpath '/export/datas/kylin_demos/data_dim_user.txt' overwrite into table `itcast_kylin_dw`.`dim_user`;
load data local inpath '/export/datas/kylin_demos/data_order_20191011.txt' overwrite into table `kylin_dw`.`fact_order` partition(dt='20191011');
load data local inpath '/export/datas/kylin_demos/data_order_20191012.txt' overwrite into table `kylin_dw`.`fact_order` partition(dt='20191012');
load data local inpath '/export/datas/kylin_demos/data_order_20191013.txt' overwrite into table `kylin_dw`.`fact_order` partition(dt='20191013');
創建增量Cube的過程和創建普通Cube的過程基本類似,只是增量Cube會有一些額外的配置要求
Hive的SQL語句
select
t1.user_id,
t2.name,
max(t1.price)
from itcast_kylin_dw.fact_order t1
left join itcast_kylin_dw.dim_user t2
on t1.user_id = t2.id
group by t1.user_id,t2.name;
Kylin操作步驟
1、配置Model
增量構建的Cube需要指定分割時間列。
例如:將日期分區字段添加到維度列中
在設置中,配置分區列,並指定日期格式
2.配置Cube
運行Cube
注意事項
注意構建Cube時,選擇的分區時間爲,起始時間(包含)、結束時間(不保存),對應了從Hive從獲取數據源的條件
INSERT OVERWRITE TABLE `kylin_intermediate_cube_order_1582ee64_45f9_cf22_bef2_e0b455efc284` SELECT `FACT_ORDER`.`DT` as `FACT_ORDER_DT` ,`FACT_ORDER`.`USER_ID` as `FACT_ORDER_USER_ID` ,`FACT_ORDER`.`PRICE` as `FACT_ORDER_PRICE` FROM `ITCAST_KYLIN_DW`.`FACT_ORDER` as `FACT_ORDER` INNER JOIN `ITCAST_KYLIN_DW`.`DIM_USER` as `DIM_USER` ON `FACT_ORDER`.`USER_ID` = `DIM_USER`.`ID` WHERE 1=1 AND (`FACT_ORDER`.`DT` >= '20191011' AND `FACT_ORDER`.`DT` < '20191012');
查看增量構建Cube對應的Segment
增量構建Cube 的時候,每個時間段 的 數據對應一個 Segment ,一個 Segement 對應一個HBase表。
二、Cube碎片管理
1、增量構建的問題
日積月累,增量構建的Cube中的Segment越來越多,該Cube的查詢性能也會越來越慢,因爲需要在單點的查詢引擎中完成越來越多的運行時聚合。爲了保持查詢性能:
-
需要定期地將某些Segment合併在一起
-
或者讓Cube根據Segment保留策略自動地淘汰那些不會再被查詢到的陳舊Segment
2、管理Cube碎片
上述案例,每天都會生成一個Segment,對應就是HBase中的一張表。增量構建的Cube每天都可能會有新的增量。這樣的Cube中最終可能包含上百個Segment,這將會導致Kylin性能受到嚴重的影響。
-
從執行引擎的角度來說,運行時的查詢引擎需要聚合多個Segment的結果才能返回正確的查詢結果
-
從存儲引擎的角度來說,大量的Segment會帶來大量的文件,給存儲空間的多個模塊帶來巨大的壓力,例如Zookeeper、HDFS Namenode等
因此,有必要採取措施控制Cube中Segment的數量。
3、手動觸發合併Segment
Kylin提供了一種簡單的機制用於控制Cube中Segment的數量:合併Segments。在Web GUI中選中需要進行Segments合併的Cube
操作步驟:
1、單擊Action→Merge
2、選中需要合併的Segment,可以同時合併多個Segment,但是這些Segment必須是連續的
單擊提交後系統會提交一個類型爲“MERGE”的構建任務,它以選中的Segment中的數據作爲輸入,將這些Segment的數據合併封裝成爲一個新的Segment。新的Segment的起始時間爲選中的最早的Segment的起始時間,它的結束時間爲選中的最晚的Segment的結束時間。
注意事項
在MERGE類型的構建完成之前,系統將不允許提交這個Cube上任何類型的其他構建任務
在MERGE構建結束之前,所有選中用來合併的Segment仍然處於可用的狀態
當MERGE構建結束的時候,系統將選中合併的Segment替換爲新的Segment,而被替換下的Segment等待將被垃圾回收和清理,以節省系統資源
3、刪除Segment
使用WebUI刪除Cube
1、disable Cube
2、點擊 delete Segment,刪除指定的segment
4、自動合併
手動維護Segment很繁瑣,人工成本很高,Kylin中是可以支持自動合併Segment。
在Cube Designer的“Refresh Settings”的頁面中有:
-
Auto Merge Thresholds
-
Retention Threshold
兩個設置項可以用來幫助管理Segment碎片。這兩項設置搭配使用這兩項設置可以大大減少對Segment進行管理的麻煩。
1、Auto Merge Thresholds
-
允許用戶設置幾個層級的時間閾值,層級越靠後,時間閾值就越大
-
每當Cube中有新的Segment狀態變爲 READY的時候,會自動觸發一次系統自動合併
-
合併策略
-
嘗試最大一級的時間閾值,例如:針對(7天、28天)層級的日誌,先檢查能否將連續的若干個Segment合併成爲一個超過28天的大Segment
-
如果有個別的Segment的時間長度本身已經超過28天,系統會跳過Segment
-
如果滿足條件的連續Segment還不能夠累積超過28天,那麼系統會使用下一個層級的時間閾值重複尋找
-
-
示例1 - 理解Kylin自動合併策略
-
假設自動合併閾值設置爲7天、28天
-
如果現在有A-H8個連續的Segment,它們的時間長度爲28天(A)、7天(B)、1天(C)、1天(D)、1天(E)、1天(F)、1天(G)、1天(H)
-
此時,第9個Segment I加入,時間長度爲1天。
自動合併策略爲:
1、Kylin判斷時候能將連續的Segment合併到28天這個閾值,由於Segment A已經超過28天,會被排除
2、剩下的連續Segment,所有時間加一起 B + C + D + E + F + G + H + I (7 + 1 + 1 + 1 + 1 + 1 + 1 + 1 = 14) < 28天,無法滿足28天閾值,開始嘗試7天閾值
3、跳過A(28)、B(7)均超過7天,排除
4、剩下的連續Segment,所有時間加一起 C + D + E + F + G + H + I(1 + 1 + 1 + 1 + 1 + 1 + 1 = 7)達到7天閾值,觸發合併,提交Merge任務。並構建一個Segment X(7天)
5、合併後,Segment爲:A(28天)、B(7天)、X(7天)
6、繼續觸發檢查,A(28天)跳過,B + X(7 + 7 = 14)< 28天,不滿足第一閾值,重新使用第二閾值觸發
7、跳過B、X,嘗試終止
- 一句話總結:局部相加 滿足小的閾值合併
2、示例:配置自動合併2天的Segment
操作步驟:
1、配置自動合併閾值爲(2、3)
2、分別按照天構建分區Cube
3、自動觸發合併Segment構建
5、配置保留Segment
自動合併是將多個Segment合併爲一個Segment,以達到清理碎片的目的。保留Segment則是及時清理不再使用的Segment。
在很多場景中,只會對過去一段時間內的數據進行查詢,例如:
-
對於某個只顯示過去1年數據的報表
-
支撐它的Cube其實只需要保留過去一年類的Segment即可
-
由於數據在Hive中已經存在備份,則無需在Kylin中備份超過一年的歷史數據
可以將Retention Threshold設置爲365。每當有新的Segment狀態變爲READY的時候,系統會檢查每一個Segment。如果它的結束時間距離最晚的一個Segment的結束時間已經大於等於“Retention Threshold”,那麼這個Segment將被視爲無需保留。系統會自動地從Cube中刪除這個Segment。
需求:
-
配置保留Segment爲2天,分別構建增量Segment,測試Segment保留情況
操作步驟:
1、在Cube中設置Retention Range爲2
2、重新構建Cube
3、測試超過指定保留時間的Segment,是否被自動移除
三、使用JDBC連接操作Kylin
-
要將數據以可視化方式展示出來,需要使用Kylin的JDBC方式連接執行SQL,獲取Kylin的執行結果
-
使用Kylin的JDBC與JDBC操作MySQL一致
-
jdbc url
-
jdbc:kylin://node01:7070/itcast_dw
-
-
用戶名密碼:ADMIN/KYLIN
-
需求
- 通過JDBC方式,查詢按照日期、區域、產品維度統計訂單總額/總數量結果
開發步驟
-
導入驅動依賴
<dependencies>
<!-- Kylin -->
<dependency>
<groupId>org.apache.kylin</groupId>
<artifactId>kylin-jdbc</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.1-jre</version>
</dependency>
</dependencies>
1、加載驅動
2、創建Connection連接對象
3、構建SQL語句
4、創建Statement對象,並執行executeQuery
5、打印結果
參考代碼
public static void main(String[] args) throws Exception {
// 1、加載驅動
Class.forName("org.apache.kylin.jdbc.Driver");
// 2、創建Connection連接對象
// 連接字符串:jdbc:kylin://ip地址:7070/項目名稱
Connection connection = DriverManager.getConnection("jdbc:kylin://node01:7070/kylin_dw_test",
"ADMIN",
"KYLIN");
// 3、創建Statement對象,並執行executeQuery,獲取ResultSet
Statement statement = connection.createStatement();
// 構建SQL和語句
String sql = "select\n" +
" t1.date1,\n" +
" t2.regionname,\n" +
" productname,\n" +
" sum(t1.price) as total_money,\n" +
" sum(t1.amount) as total_amount\n" +
"from\n" +
" dw_sales t1\n" +
"inner join dim_region t2\n" +
"on t1.regionid = t2.regionid\n" +
"inner join dim_product t3\n" +
"on t1.productid = t3.productid\n" +
"group by\n" +
" t1.date1,\n" +
" t2.regionid,\n" +
" t2.regionname,\n" +
" t3.productid,\n" +
" t3.productname";
ResultSet resultSet = statement.executeQuery(sql);
// 4、打印ResultSet
while(resultSet.next()) {
// 4.1 獲取時間
String date1 = resultSet.getString("date1");
// 4.2 獲取區域名稱
String regionname = resultSet.getString("regionname");
// 4.3 獲取產品名稱
String productname = resultSet.getString("productname");
// 4.4 總金額
String total_money = resultSet.getString("total_money");
// 4.5 總數量
String total_amount = resultSet.getString("total_amount");
System.out.println(date1 + " " + regionname + " " + productname + " " + total_money + " " + total_amount);
}
connection.close();
}
四、Kylin Cube優化-Cuboid剪枝優化
1、爲什麼要進行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接近,因此顯得多餘
Kylin提供了一系列簡單的工具來幫助他們完成Cube的剪枝優化
2、檢查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 KYLIN_DW.FACT_ORDER.DT is 1
Length of dimension 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都是在它的父親節點的基礎上進一步聚合而成的
3、檢查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膨脹率居高不下的情況,需要結合實際數據進行分析,優化。
4、使用衍生維度
示例:
-
有兩張表 用戶維度表(dim_user)、訂單事實表(fact_order),要根據各個維度建立MOLAP立方體
用戶維度表(dim_user)
訂單事實表(fact_order)
問題:
- 生成Cube時,如果指定維度表中的:姓名、出生年份、政治面貌、職業、性別、民族、省份、市、區等維度生成Cube,這些維度相互組合,會造成較大的Cube膨脹率
使用衍生維度用於在有效維度內將維度表上的非主鍵維度排除掉,並使用維度表的主鍵(其實是事實表上相應的外鍵)來替代它們。Kylin會在底層記錄維度表主鍵與維度表其他維度之間的映射關係,以便在查詢時能夠動態地將維度表的主鍵“翻譯”成這些非主鍵維度,並進行 實時聚合。
創建Cube的時候,這些維度如果指定爲衍生維度,Kylin將會排除這些維度,而是使用維度表的主鍵來代替它們創建Cuboid。後續查詢的時候,再基於主鍵的聚合結果,再進行一次聚合。
- 優化效果:維度表的N個維度組合成的cuboid個數會從2^N降爲2。
- 只把normal 類型的維度列生成爲 Cuboid
不適用的場景:
-
如果從維度表主鍵到某個維度表維度所需要的聚合工作量非常大,此時作爲一個普通的維度聚合更合適,否則會影響Kylin的查詢性能
美團“維度爆炸”問題在實踐中是可解的
提到MOLAP Cube方案,很多沒接觸過Kylin的人會擔心“維度爆炸”的問題,即每增加一個維度,由於維度組合數翻倍,Cube的計算和存儲量也會成倍增長。我們起初其實也有同樣的擔心,但調研和使用Kylin一陣子後發現,這個問題在實踐中並沒有想象的嚴重。這主要是因爲
-
Kylin支持Partial Cube,不需要對所有維度組合都進行預計算
-
實際業務中,維度之間往往存在衍生關係,而Kylin可以把衍生維度的計算從預計算推遲到查詢處理階段
以事實表上的衍生維度爲例,我們業務中的很多維度都是(ID, NAME)成對出現的。查詢時需要對ID列進行過濾,但顯示時只需要取對應的NAME列。如果把這兩列都作爲維度,維度個數會翻倍。而在Kylin中,可以把NAME作爲ID列的extendedcolumn指標,這樣Cube中的維度個數就減半了。
下面分享一些我們線上Cube的統計數據。
可以看到,採用衍生維度後,90%的場景可以把Cube中的維度個數(Rowkey列數)控制在20個以內。指標個數呈現長尾分佈,小於10個指標的Cube是最多的,不過也有近一半的Cube指標數超過20。總共有382個去重指標,佔到了總指標數的10%,絕大多數都是精確去重指標。49%的Cube膨脹率小於100%,即Cube存儲量不超過上游Hive表。68%的Cube能夠在1小時內完成構建,92%在2小時內完成構建。
5、聚合組
-
聚合組(Aggregation Group)是一種更強大的剪枝工具
-
聚合組假設一個Cube的 所有維度 均可以根據業務需求劃分成若干組
-
同一個組內的維度更可能同時被同一個查詢用到,每個分組的維度集合均是 Cube 所有維度的一個子集
-
不同的分組各自擁有一套維度集合,它們可能與其他分組有相同的維度,也可能沒有相同的維度
-
每個分組各自獨立地根據自身的規則貢獻出一批需要被物化的Cuboid,所有分組貢獻的Cuboid的並集就成爲了當前Cube中所有需要物化的Cuboid的集合
-
不同的分組有可能會貢獻出相同的Cuboid,構建引擎會察覺到這點,並且保證每一個Cuboid無論在多少個分組中出現,它都只會被物化一次
對於每個分組內部的維度,用戶可以使用如下三種可選的方式定義它們之間的關係,具體如下:
-
強制維度(Mandatory)
-
如果一個維度被定義爲強制維度,那麼這個分組產生的所有Cuboid中每一個Cuboid都會包含該維度。所有cuboid必須包含的維度,不會計算不包含強制維度的cuboid
-
每個分組中都可以有0個、1個或多個強制維度
-
如果根據這個分組的業務邏輯,則相關的查詢一定會在過濾條件或分組條件中,因此可以在該分組中把該維度設置爲強制維度
-
適用場景
-
可以將確定在查詢時一定會使用的維度設爲強制維度。例如,時間維度。
-
-
優化效果
-
將一個維度設爲強制維度,則cuboid個數直接減半
-
-
-
層級維度(Hierarchy)
-
每個層級包含兩個或更多個維度
-
假設一個層級中包含D1,D2…Dn這n個維度,那麼在該分組產生的任何Cuboid中,這n個維度只會以(),(D1),(D1,D2)…(D1,D2…Dn)這n+1種形式中的一種出現
-
每個分組中可以有0個、1個或多個層級,不同的層級之間不應當有共享的維度
-
如果根據這個分組的業務邏輯,則多個維度直接存在層級關係,因此可以在該分組中把這些維度設置爲層級維度
-
使用場景
-
年,月,日;國家,省份,城市這類具有層次關係的維度
-
-
優化效果
-
將N個維度設置爲層次維度,則這N個維度組合成的cuboid個數會從2^n -1 減少到N
-
-
-
聯合維度(Joint)
-
每個聯合中包含兩個或更多個維度,如果某些列形成一個聯合,那麼在該分組產生的任何Cuboid中,這些聯合維度要麼一起出現,要麼都不出現
-
每個分組中可以有0個或多個聯合,但是不同的聯合之間不應當有共享的維度(否則它們可以合併成一個聯合)。如果根據這個分組的業務邏輯,多個維度在查詢中總是同時出現,則可以在該分組中把這些維度設置爲聯合維度
-
適用場景
-
可以將確定在查詢時一定會同時使用的幾個維度設爲一個聯合維度
-
-
優化效果
-
將N個維度設置爲聯合維度,則這N個維度組合成的cuboid個數會從2^n-1減少到1
-
-