Apache Kylin 入門系列目錄
- Apache Kylin 入門 1 - 基本概念
- Apache Kylin 入門 2 - 原理與架構
- Apache Kylin 入門 3 - 安裝配置引數詳解
- Apache Kylin 入門 4 - 構建 Model
- Apache Kylin 入門 5 - 構建 Cube
- Apache Kylin 入門 6 - 優化 Cube
- 基於 ELKB 構建 Kylin 查詢時間監控頁面
由於業務需求不盡相同,本文不使用具體的案例進行演示,文章會更加傾向於對構建過程中的選項和注意事項進行全方位闡述。
一、Cube Info
Cube Info 介面主要填寫 Cube 的一些基本資訊,首先要選擇一個資料模型,然後填寫 Cube 名稱,Cube 名稱全域性唯一不能重複;Cube 資訊填寫完成後點選 “Next” 進入下一步。
二、Dimensions
Dimensions 是維度選擇介面,從資料模型的維度中選擇一些列作為 Cube 的維度,這個算是 Cube 構建過程中第一個比較重要的環節,這裡的設定會影響到生成的 Cuboid 數量,進而影響 Cube 的資料量大小。
在選擇維度時,每一個維度列可以作為普通維度(Normal),也可以作為衍生維度(Derived)。相對於普通維度來說,衍生維度並不參與維度的 Cuboid,衍生維度對應的外來鍵(FK)參與維度 Cuboid,從而降低 Cuboid 數。在查詢時,對衍生維度的查詢會首先轉換為對外來鍵所在維度的查詢,因此會犧牲少量效能(大部分情況下可以接受)。
1、維度選擇的建議:
- 作為 Cube 的維度需要滿足下面的條件:可能存在於 where 條件中或者 groupBy 中的維度;
- 事實表(Fact Table)只選擇參與查詢的欄位,不參與查詢的一定不要勾選(即便是外來鍵);
- 維度表(Lookup Table)中的主鍵與事實表的外來鍵一一對應,推薦勾選事實表的外來鍵,維度表的主鍵勾選後選擇為衍生(Derived)維度;
- 對於星型模型而言,維度表的欄位往往可以全部為衍生欄位;
- 對於雪花模型而言,如果維度表存在子表,則維度表對於子表的外來鍵推薦作為普通(Normal)維度。
2、特別注意的事項:
- 表連線的欄位並非一定要參與 Cuboid 計算;
- 表連線的欄位如果沒有被勾選,且其外來鍵表中沒有任何欄位作為衍生維度,則該表連線欄位是不會參與 Cuboid 的;
- 一旦被設定為 Normal 型別,則一定會參與 Cuboid 計算;
- 如果維度表存在層級(例如省市縣、日月年等),則推薦分層級的相關欄位選擇為普通(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倍)的紀錄, 並供以後再次合併。
2、Count_Distinct
Count_Distinct 度量有兩個實現:
- 近似實現:基於 HyperLogLog 演算法,可選擇接受的錯誤率(從9.75% 到 1.22%),低錯誤率需要更多儲存;
- 精確實現:基於 Bitmap(點陣圖)演算法,對於資料型為 tinyint、smallint 和 int 的資料,將把資料對應的值直接打入點陣圖;對於資料型為 long,string 和其他的數 據,將它們編碼成字串放入字典,然後再將對應的值打入點陣圖。返回的度量結果是已經序列化的點陣圖資料,而不僅是計算的值。這確保了不同的 segment 中,甚至跨越不同的 segment 來上卷,結果也是正確的。
越精確消耗的儲存空間越大,大多數場景下 HyperLogLog 的近似實現即可滿足需求。
3、EXTEND_COLUMN
在分析場景中,經常存在對某個 id 進行過濾,但查詢結果要展示為 name 的情況,比如user_id
和user_name
。這類問題通常有三種解決方式:
- 將 id 和 name 都設定為維度,查詢語句類似
select name, count(*) from table where id = 1 group by id,name
,這種方式的問題是會導致維度增多,導致預計算結果膨脹; - 將 id 和 name 都設定為維度,並且將兩者設定為聯合維度(Joint Dimensions),這種方式的好處是保持維度組合數不會增加,但限制了維度的其它優化,比如 id 不能再被設定為強制維度或者層次維度;
- 將 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 裡面被稱為聚合組。例如查詢需求為:汙染物排放量在特定的時間範圍內,各個區域(省、市、區縣三個級別)的排名以及各個流域(一、二、三級流域)的排名。
上述的查詢需求就可以氛圍兩個聚合組:
- 根據區域維度、時間維度查詢汙染物排放量;
- 根據流域維度、時間維度查詢汙染物排放量。
如果只使用一個聚合組,區域維度和流域維度就很產生很多組合的 Cuboid,然而這些組合對查詢毫無用處,此時就可以使用兩個聚合組把區域和流域分開,這樣便可以大大減少無用的組合。
2、必要維度(Mandatory Dimension)
Mandatory 維度指的是那些總是會出現 在Where 條件或 Group By 語句裡的維度。
當然必須存在不一定是顯式出現在查詢語句中,例如查詢日期是必要欄位,月份、季度、年屬於它的衍生欄位,那麼查詢的時候出現月份、季度、年這些衍生欄位等效於出現查詢日期這個必要欄位。
3、層級維度 (Hierachy Dimension)
Hierarchy 是一組有層級關係的維度,例如:國家->省->市,這裡的“國家”是高階別的維度,“省”“市”依次是低階別的維度;使用者會按高階別維度進行查詢,也會按低階別維度進行查詢,但在查詢低階別維度時,往往都會帶上高階別維度的條件,而不會孤立地審視低階別維度的資料。也就是說,使用者對於這三個維度的查詢可以歸類為以下三類:
- group by country
- group by country, province(等同於group by province)
- 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 進行調整。
Any Code,Code Any!
掃碼關注『AnyCode』,程式設計路上,一起前行。