Apache Kylin 入門 5 - 構建 Cube

rochy_he發表於2018-10-28

Apache Kylin 入門系列目錄

由於業務需求不盡相同,本文不使用具體的案例進行演示,文章會更加傾向於對構建過程中的選項和注意事項進行全方位闡述。

一、Cube Info

Cube Info 介面主要填寫 Cube 的一些基本資訊,首先要選擇一個資料模型,然後填寫 Cube 名稱,Cube 名稱全域性唯一不能重複;Cube 資訊填寫完成後點選 “Next” 進入下一步。

Cube 基本資訊填寫

二、Dimensions

Dimensions 是維度選擇介面,從資料模型的維度中選擇一些列作為 Cube 的維度,這個算是 Cube 構建過程中第一個比較重要的環節,這裡的設定會影響到生成的 Cuboid 數量,進而影響 Cube 的資料量大小。

在選擇維度時,每一個維度列可以作為普通維度(Normal),也可以作為衍生維度(Derived)。相對於普通維度來說,衍生維度並不參與維度的 Cuboid,衍生維度對應的外來鍵(FK)參與維度 Cuboid,從而降低 Cuboid 數。在查詢時,對衍生維度的查詢會首先轉換為對外來鍵所在維度的查詢,因此會犧牲少量效能(大部分情況下可以接受)。

維度選擇介面

1、維度選擇的建議:

  1. 作為 Cube 的維度需要滿足下面的條件:可能存在於 where 條件中或者 groupBy 中的維度;
  2. 事實表(Fact Table)只選擇參與查詢的欄位,不參與查詢的一定不要勾選(即便是外來鍵)
  3. 維度表(Lookup Table)中的主鍵與事實表的外來鍵一一對應,推薦勾選事實表的外來鍵,維度表的主鍵勾選後選擇為衍生(Derived)維度;
  4. 對於星型模型而言,維度表的欄位往往可以全部為衍生欄位;
  5. 對於雪花模型而言,如果維度表存在子表,則維度表對於子表的外來鍵推薦作為普通(Normal)維度。

2、特別注意的事項:

  1. 表連線的欄位並非一定要參與 Cuboid 計算;
  2. 表連線的欄位如果沒有被勾選,且其外來鍵表中沒有任何欄位作為衍生維度,則該表連線欄位是不會參與 Cuboid 的;
  3. 一旦被設定為 Normal 型別,則一定會參與 Cuboid 計算;
  4. 如果維度表存在層級(例如省市縣、日月年等),則推薦分層級的相關欄位選擇為普通(Normal)維度。

維度選擇結果

三、Measures

維度選擇完成後,需要選擇度量聚合的方式,比較常規的聚合方式有:COUNT、SUM、MIN、MAX、PERCENTILE,下面將詳細介紹其他幾種聚合方式。

1、TOP_N

Top-N 度量,旨在在 Cube 構建的時候預計算好需要的 Top-N;在查詢階段,就可以迅速的獲取並返回 Top-N 記錄,這樣查詢效能就遠遠高於沒有 Top-N 預計算結果的 Cube。

1.1、Top-N 中 Group By 的該如何選擇?

例如:全國二氧化碳汙染物總和的省份排名,結果是省份排名,需要測量的是汙染物的總和,因此 Group By 需要設定為 汙染物型別。

1.2、Return Type 中的 Top N 是什麼意思?

TOP N 表示最終獲取的前 N 名的排序是比較準確的,例如 TOP 10 表示最終的前 10 名是比較準確的(維度的基數非常大時存在誤差),但是不代表只能取前 10 個(Limit 10),可以使用其他數字,例如 Limit 500,只是返回更多內容時,精準度沒有保證。

1.3、TOP-N 的儲存

使用 TOP-N 時,排序度量欄位和 Group By 欄位會組合在一起,形成一個欄位進行儲存,使用者需要 Top 100 的結果,Kylin 對於每種組合條件值,保留 Top 5000 (50倍)的紀錄, 並供以後再次合併。

TOP-N 內部儲存結構

2、Count_Distinct

Count_Distinct 度量有兩個實現:

  1. 近似實現:基於 HyperLogLog 演算法,可選擇接受的錯誤率(從9.75% 到 1.22%),低錯誤率需要更多儲存;
  2. 精確實現:基於 Bitmap(點陣圖)演算法,對於資料型為 tinyint、smallint 和 int 的資料,將把資料對應的值直接打入點陣圖;對於資料型為 long,string 和其他的數 據,將它們編碼成字串放入字典,然後再將對應的值打入點陣圖。返回的度量結果是已經序列化的點陣圖資料,而不僅是計算的值。這確保了不同的 segment 中,甚至跨越不同的 segment 來上卷,結果也是正確的。

越精確消耗的儲存空間越大,大多數場景下 HyperLogLog 的近似實現即可滿足需求。

3、EXTEND_COLUMN

在分析場景中,經常存在對某個 id 進行過濾,但查詢結果要展示為 name 的情況,比如user_iduser_name。這類問題通常有三種解決方式:

  1. 將 id 和 name 都設定為維度,查詢語句類似select name, count(*) from table where id = 1 group by id,name,這種方式的問題是會導致維度增多,導致預計算結果膨脹;
  2. 將 id 和 name 都設定為維度,並且將兩者設定為聯合維度(Joint Dimensions),這種方式的好處是保持維度組合數不會增加,但限制了維度的其它優化,比如 id 不能再被設定為強制維度或者層次維度;
  3. 將 id 設定為維度,name 設定為特殊的 Measure,型別為 Extended Column,這種方式既能保證過濾 id 且查詢 name 的需求,同時也不影響 id 維度的進一步優化。

四、Refresh Setting

  • 觸發自動合併的時間閾值(Auto Merge Thresholds):自動合併小的 segments 到中等甚至更大的 segment,如果不想自動合併,刪除預設 2 個選項;
  • Volatile Range: 預設為 0,‘Auto Merge’ 會自動合併所有可能的 cube segments;設定具體的數值後,‘Auto Merge’ 將不會合並最近 Volatile Range 天的 cube segments;假設 Volatile Range 設定為 7,則最近 7 天內生成的 cube segments 不會被自動合併;
  • 保留時間閾值(Retention Threshold):對於時間久遠的不需要再被查詢的 Segment,Kylin 通過設定保留時間閾值可以自動清除這些 Segment,以節省磁碟空間;每當構建新的 Segment 時,Kylin 會自動檢查老的 Segment,當這些 Segment 的結束日期與當前最新 Segment 的結束日期的差值大於保留時間閾值,則會被清除;如果無需自動清理,可以預設設定保留時間閾值為 0。
  • 分割槽起始時間(Partition Start Date):Cube 構建的起始時間,1970-01-01 08:00:00 預設為分割槽起始時間。

五、Advanced Setting

高階設定主要用於 Cuboid 的剪枝優化,通過聚合組(Aggregation Group)、必要維度(Mandatory Dimension)、層級維度(Hierarchy Dimension)、聯合維度(Joint Dimension)等方式,可以使得 Cuboid 的組合在預期範圍內。

1、聚合組(Aggregation Group)

根據查詢的維度組合,可以劃分出維度組合大類,這些大類在 Kylin 裡面被稱為聚合組。例如查詢需求為:汙染物排放量在特定的時間範圍內,各個區域(省、市、區縣三個級別)的排名以及各個流域(一、二、三級流域)的排名。

上述的查詢需求就可以氛圍兩個聚合組:

  1. 根據區域維度、時間維度查詢汙染物排放量;
  2. 根據流域維度、時間維度查詢汙染物排放量。

如果只使用一個聚合組,區域維度和流域維度就很產生很多組合的 Cuboid,然而這些組合對查詢毫無用處,此時就可以使用兩個聚合組把區域和流域分開,這樣便可以大大減少無用的組合。

2、必要維度(Mandatory Dimension)

Mandatory 維度指的是那些總是會出現 在Where 條件或 Group By 語句裡的維度

當然必須存在不一定是顯式出現在查詢語句中,例如查詢日期是必要欄位,月份、季度、年屬於它的衍生欄位,那麼查詢的時候出現月份、季度、年這些衍生欄位等效於出現查詢日期這個必要欄位。

3、層級維度 (Hierachy Dimension)

Hierarchy 是一組有層級關係的維度,例如:國家->省->市,這裡的“國家”是高階別的維度,“省”“市”依次是低階別的維度;使用者會按高階別維度進行查詢,也會按低階別維度進行查詢,但在查詢低階別維度時,往往都會帶上高階別維度的條件,而不會孤立地審視低階別維度的資料。也就是說,使用者對於這三個維度的查詢可以歸類為以下三類:

  1. group by country
  2. group by country, province(等同於group by province)
  3. group by country, province, city(等同於group by country, city 或者group by city)

4、聯合維度(Joint Dimension)

有些維度往往一起出現,或者它們的基數非常接近(有1:1對映關係),例如 “user_id” 和 “email”。把多個維度定義為組合關係後,所有不符合此關係的 cuboids 會被跳過計算。

Joint Dimension (A, B) 來說,在 group by 時 A, B 最好同時出現,這樣不損失效能。但如果只出現 A 或者 B,那麼就需要在查詢時從 group by A,B 的結果做進一步聚合運算,會降低查詢的速度。

5、Rowkeys

5.1、編碼

Kylin 以 Key-Value 的方式將 Cube 儲存到 HBase 中,HBase 的 key,也就是 Rowkey,是由各維度的值拼接而成的;為了更高效地儲存這些值,Kylin 會對它們進行編碼和壓縮;每個維度均可以選擇合適的編碼(Encoding)方式,預設採用的是字典(Dictionary)編碼技術;欄位支援的基本編碼型別如下:

  • dict:適用於大部分欄位,預設推薦使用,但在超高基情況下,可能引起記憶體不足的問題;
  • boolean:適用於欄位值為true, false, TRUE, FALSE, True, False, t, f, T, F, yes, no, YES, NO, Yes, No, y, n, Y, N, 1, 0
  • integer:適用於欄位值為整數字符,支援的整數區間為[ -2^(8N-1), 2^(8N-1)]
  • date:適用於欄位值為日期字元,支援的格式包括yyyyMMdd、yyyy-MM-dd、yyyy-MM-dd HH:mm:ss、yyyy-MM-dd HH:mm:ss.SSS,其中如果包含時間戳部分會被截斷;
  • time:適用於欄位值為時間戳字元,支援範圍為[ 1970-01-01 00:00:00, 2038/01/19 03:14:07],毫秒部分會被忽略,time編碼適用於 time, datetime, timestamp 等型別;
  • fix_length適用於超高基場景,將選取欄位的前 N 個位元組作為編碼值,當 N 小於欄位長度,會造成欄位截斷,當 N 較大時,造成 RowKey 過長,查詢效能下降,只適用於 varchar 或 nvarchar 型別;
  • fixed_length_hex:適用於欄位值為十六進位制字元,比如 1A2BFF 或者 FF00FF,每兩個字元需要一個位元組,只適用於 varchar 或 nvarchar 型別。

5.2、順序

各維度在 Rowkeys 中的順序,對於查詢的效能會產生較明顯的影響;在這裡使用者可以根據查詢的模式和習慣,通過拖曳的方式調整各個維度在Rowkeys上的順序。推薦的順序為:Mandatory 維度、where 過濾條件中出現頻率較多的維度、高基數維度、低基數維度。這樣做的好處是,充分利用過濾條件來縮小在 HBase 中掃描的範圍,從而提高查詢的效率。

5.3、分片

指定 ShardBy 的列,明細資料將按照該列的值分片;沒有指定 ShardBy 的列,則預設將根據所有列中的資料進行分片;選擇適當的 ShardBy 列,可以使明細資料較為均勻的分散在多個資料片上,提高並行性,進而獲得更理想的查詢效率;建議選擇基數較大的列作為 ShardBy 列,以避免資料分散不均勻

6、其他設定

  • Mandatory Cuboids: 維度組合白名單,指定需要構建的 cuboid 的維度的組合;
  • Cube Engine: Cube 構建引擎,有兩種:MapReduce 和 Spark;如果你的 Cube 只有簡單度量(SUM, MIN, MAX),建議使用 Spark;如果 Cube 中有複雜型別度量(COUNT DISTINCT, TOP_N),建議使用 MapReduce;
  • Global Dictionary:用於精確計算 COUNT DISTINCT 的字典, 它會將一個非 integer 的值轉成 integer,以便於 bitmap 進行去重;如果你要計算 COUNT DISTINCT 的列本身已經是 integer 型別,那麼不需要定義 Global Dictionary; Global Dictionary 會被所有 segment 共享,因此支援在跨 segments 之間做上捲去重操作。
  • Segment Dictionary:另一個用於精確計算 COUNT DISTINCT 的字典,與 Global Dictionary 不同的是,它是基於一個 segment 的值構建的,因此不支援跨 segments 的彙總計算。如果你的 cube 不是分割槽的或者能保證你的所有 SQL 按照 partition_column 進行 group by, 那麼你應該使用 “Segment Dictionary” 而不是 “Global Dictionary”,這樣可以避免單個字典過大的問題。
  • Advanced Snapshot Table: 為全域性 lookup 表而設計,提供不同的儲存型別;
  • Advanced ColumnFamily: 如果有超過一個的 COUNT DISTINCT 或 TopN 度量, 你可以將它們放在更多列簇中,以優化與HBase 的I/O。

六、Configuration Overwrites

Kylin 使用了很多配置引數以提高靈活性,使用者可以根據具體的環境、場景等配置不同的引數進行調優;Kylin 全域性的引數值可在 conf/kylin.properties 檔案中進行配置;如果 Cube 需要覆蓋全域性設定的話,則需要在此頁面中指定,這些配置項將覆蓋專案級別和配置檔案中的預設值。

配置重寫覆蓋

七、Overview

你可以概覽你的 cube 並返回之前的步驟進行修改,點選 Save 按鈕完成 cube 建立。

概覽與儲存

八、Planner

如果你開啟了 Cube Planner,當 Cube 儲存後可以到 Planner 標籤頁檢視 Cuboid 的個數以及各個維度的組合情況,這能夠很直觀的幫助你瞭解你的維度組合情況,如果與預想的有出入可以隨時對 Cube 進行調整。

通過 Cube Planner 檢視 Cuboid


Any Code,Code Any!

掃碼關注『AnyCode』,程式設計路上,一起前行。

Apache Kylin 入門 5 - 構建 Cube

相關文章