天天看點

Kylin快速入門系列(4) | Cube建構優化一. 使用衍生次元(derived dimension)二. 使用聚合組(Aggregation group)四. Row Key優化五. 并發粒度優化

上一篇博文我們已經介紹過,在沒有采取任何優化措施的情況下,Kylin會對每一種次元的組合進行預計算,每種次元的組合的預計算結果被稱為Cuboid。假設有4個次元,我們最終會有24 =16個Cuboid需要計算。

  但在現實情況中,使用者的次元數量一般遠遠大于4個。假設使用者有10 個次元,那麼沒有經過任何優化的Cube就會存在210 =1024個Cuboid;而如果使用者有20個次元,那麼Cube中總共會存在220 =1048576個Cuboid。雖然每個Cuboid的大小存在很大的差異,但是單單想到Cuboid的數量就足以讓人想象到這樣的Cube對建構引擎、存儲引擎來說壓力有多麼巨大。是以,在建構次元數量較多的Cube時,尤其要注意Cube的

剪枝優化

(即減少Cuboid的生成)。

一. 使用衍生次元(derived dimension)

  衍生次元用于在有效次元内将次元表上的非主鍵次元排除掉,并使用次元表的主鍵(其實是事實表上相應的外鍵)來替代它們。Kylin會在底層記錄次元表主鍵與次元表其他次元之間的映射關系,以便在查詢時能夠動态地将次元表的主鍵“翻譯”成這些非主鍵次元,并進行實時聚合。

原理如下:

Kylin快速入門系列(4) | Cube建構優化一. 使用衍生次元(derived dimension)二. 使用聚合組(Aggregation group)四. Row Key優化五. 并發粒度優化
Kylin快速入門系列(4) | Cube建構優化一. 使用衍生次元(derived dimension)二. 使用聚合組(Aggregation group)四. Row Key優化五. 并發粒度優化

  雖然衍生次元具有非常大的吸引力,但這也并不是說所有次元表上的次元都得變成衍生次元,如果從次元表主鍵到某個次元表次元所需要的聚合工作量非常大,則不建議使用衍生次元。

二. 使用聚合組(Aggregation group)

  聚合組(Aggregation Group)是一種強大的剪枝工具。聚合組假設一個Cube的所有次元均可以根據業務需求劃分成若幹組(當然也可以是一個組),由于同一個組内的次元更可能同時被同一個查詢用到,是以會表現出更加緊密的内在關聯。每個分組的次元集合均是Cube所有次元的一個子集,不同的分組各自擁有一套次元集合,它們可能與其他分組有相同的次元,也可能沒有相同的次元。每個分組各自獨立地根據自身的規則貢獻出一批需要被物化的Cuboid,所有分組貢獻的Cuboid的并集就成為了目前Cube中所有需要物化的Cuboid的集合。不同的分組有可能會貢獻出相同的Cuboid,建構引擎會察覺到這點,并且保證每一個Cuboid無論在多少個分組中出現,它都隻會被物化一次。

  對于每個分組内部的次元,使用者可以使用如下三種可選的方式定義,它們之間的關系,具體如下。

  1.

強制次元(Mandatory)

,如果一個次元被定義為強制次元,那麼這個分組産生的所有Cuboid中每一個Cuboid都會包含該次元。每個分組中都可以有0個、1個或多個強制次元。如果根據這個分組的業務邏輯,則相關的查詢一定會在過濾條件或分組條件中,是以可以在該分組中把該次元設定為強制次元。

Kylin快速入門系列(4) | Cube建構優化一. 使用衍生次元(derived dimension)二. 使用聚合組(Aggregation group)四. Row Key優化五. 并發粒度優化

  2.

層級次元(Hierarchy)

,每個層級包含兩個或更多個次元。假設一個層級中包含D1,D2…Dn這n個次元,那麼在該分組産生的任何Cuboid中, 這n個次元隻會以(),(D1),(D1,D2)…(D1,D2…Dn)這n+1種形式中的一種出現。每個分組中可以有0個、1個或多個層級,不同的層級之間不應當有共享的次元。如果根據這個分組的業務邏輯,則多個次元直接存在層級關系,是以可以在該分組中把這些次元設定為層級次元。

Kylin快速入門系列(4) | Cube建構優化一. 使用衍生次元(derived dimension)二. 使用聚合組(Aggregation group)四. Row Key優化五. 并發粒度優化

  3.

聯合次元(Joint)

,每個聯合中包含兩個或更多個次元,如果某些列形成一個聯合,那麼在該分組産生的任何Cuboid中,這些聯合次元要麼一起出現,要麼都不出現。每個分組中可以有0個或多個聯合,但是不同的聯合之間不應當有共享的次元(否則它們可以合并成一個聯合)。如果根據這個分組的業務邏輯,多個次元在查詢中總是同時出現,則可以在該分組中把這些次元設定為聯合次元。

Kylin快速入門系列(4) | Cube建構優化一. 使用衍生次元(derived dimension)二. 使用聚合組(Aggregation group)四. Row Key優化五. 并發粒度優化

這些操作可以在Cube Designer的Advanced Setting中的Aggregation Groups區域完成,如下圖所示。

Kylin快速入門系列(4) | Cube建構優化一. 使用衍生次元(derived dimension)二. 使用聚合組(Aggregation group)四. Row Key優化五. 并發粒度優化

  聚合組的設計非常靈活,甚至可以用來描述一些極端的設計。假設我們的業務需求非常單一,隻需要某些特定的Cuboid,那麼可以建立多個聚合組,每個聚合組代表一個Cuboid。具體的方法是在聚合組中先包含某個Cuboid所需的所有次元,然後把這些次元都設定為強制次元。這樣目前的聚合組就隻能産生我們想要的那一個Cuboid了。

  再比如,有的時候我們的Cube中有一些基數非常大的次元,如果不做特殊處理,它就會和其他的次元進行各種組合,進而産生一大堆包含它的Cuboid。包含高基數次元的Cuboid在行數和體積上往往非常龐大,這會導緻整個Cube的膨脹率變大。如果根據業務需求知道這個高基數的次元隻會與若幹個次元(而不是所有次元)同時被查詢到,那麼就可以通過聚合組對這個高基數次元做一定的“隔離”。我們把這個高基數的次元放入一個單獨的聚合組,再把所有可能會與這個高基數次元一起被查詢到的其他次元也放進來。這樣,這個高基數的次元就被“隔離”在一個聚合組中了,所有不會與它一起被查詢到的次元都沒有和它一起出現在任何一個分組中,是以也就不會有多餘的Cuboid産生。這點也大大減少了包含該高基數次元的Cuboid的數量,可以有效地控制Cube的膨脹率。

四. Row Key優化

  Kylin會把所有的次元按照順序組合成一個完整的Rowkey,并且按照這個Rowkey升序排列Cuboid中所有的行。

  設計良好的Rowkey将更有效地完成資料的查詢過濾和定位,減少IO次數,提高查詢速度,次元在rowkey中的次序,對查詢性能有顯著的影響。

Row key的設計原則如下:

  • 1. 被用作where過濾的次元放在前邊。
Kylin快速入門系列(4) | Cube建構優化一. 使用衍生次元(derived dimension)二. 使用聚合組(Aggregation group)四. Row Key優化五. 并發粒度優化
  • 2. 基數大的次元放在基數小的次元前邊。
Kylin快速入門系列(4) | Cube建構優化一. 使用衍生次元(derived dimension)二. 使用聚合組(Aggregation group)四. Row Key優化五. 并發粒度優化

五. 并發粒度優化

  當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最少或最多被劃分成多少個分區。

Kylin快速入門系列(4) | Cube建構優化一. 使用衍生次元(derived dimension)二. 使用聚合組(Aggregation group)四. Row Key優化五. 并發粒度優化

  由于每個Cube的并發粒度控制不盡相同,是以建議在Cube Designer 的Configuration Overwrites(上圖所示)中為每個Cube量身定制控制并發粒度的參數。假設将把目前Cube的kylin.hbase.region.count.min設定為2,kylin.hbase.region.count.max設定為100。這樣無論Segment的大小如何變化,它的分區數量最小都不會低于2,最大都不會超過100。相應地,這個Segment背後的存儲引擎(HBase)為了存儲這個Segment,也不會使用小于兩個或超過100個的分區。我們還調整了預設的kylin.hbase.region.cut,這樣50GB的Segment基本上會被配置設定到50個分區,相比預設設定,我們的Cuboid可能最多會獲得5倍的并發量。

  本次的分享就到這裡