Kylin Cube構(gòu)建原理+調(diào)優(yōu)
點(diǎn)擊上方藍(lán)色字體,選擇“設(shè)為星標(biāo)”

作者:Knight_AL
原文:http://suo.im/6fNLaO
目錄
Kylin Cube構(gòu)建原理
維度和度量
Cube和Cuboid
Cube構(gòu)建算法
Cube存儲(chǔ)原理
Kylin Cube構(gòu)建優(yōu)化
使用衍生維度(derived dimension)
使用聚合組(Aggregation group)
Row Key優(yōu)化
并發(fā)粒度優(yōu)化
Kylin Cube構(gòu)建原理
維度和度量
維度:即觀察數(shù)據(jù)的角度。比如員工數(shù)據(jù),可以從性別角度來分析,也可以更加細(xì)化,從入職時(shí)間或者地區(qū)的維度來觀察。維度是一組離散的值,比如說性別中的男和女,或者時(shí)間維度上的每一個(gè)獨(dú)立的日期。因此在統(tǒng)計(jì)時(shí)可以將維度值相同的記錄聚合在一起,然后應(yīng)用聚合函數(shù)做累加、平均、最大和最小值等聚合計(jì)算。度量:即被聚合(觀察)的統(tǒng)計(jì)值,也就是聚合運(yùn)算的結(jié)果。比如說員工數(shù)據(jù)中不同性別員工的人數(shù),又或者說在同一年入職的員工有多少。
Cube和Cuboid
有了維度跟度量,一個(gè)數(shù)據(jù)表或者數(shù)據(jù)模型上的所有字段就可以分類了,它們要么是維度,要么是度量(可以被聚合)。于是就有了根據(jù)維度和度量做預(yù)計(jì)算的Cube理論。
給定一個(gè)數(shù)據(jù)模型,我們可以對(duì)其上的所有維度進(jìn)行聚合,對(duì)于N個(gè)維度來說,組合的所有可能性共有2n種。對(duì)于每一種維度的組合,將度量值做聚合計(jì)算,然后將結(jié)果保存為一個(gè)**物化視圖`**,稱為Cuboid。所有維度組合的Cuboid作為一個(gè)整體,稱為Cube。
下面舉一個(gè)簡單的例子說明,假設(shè)有一個(gè)電商的銷售數(shù)據(jù)集,其中維度包括時(shí)間[time]、商品[item]、地區(qū)[location]和供應(yīng)商[supplier],度量為銷售額。那么所有維度的組合就有24 = 16種,如下圖所示:
一維度(1D)的組合有:[time]、[item]、[location]和[supplier]4種;
二維度(2D)的組合有:[time, item]、[time, location]、[time, supplier]、[item, location]、[item, supplier]、[location, supplier]3種;
三維度(3D)的組合也有4種;
最后還有零維度(0D)和四維度(4D)各有一種,總共16種。
注意:每一種維度組合就是一個(gè)Cuboid,16個(gè)Cuboid整體就是一個(gè)Cube。
Cube構(gòu)建算法
1)逐層構(gòu)建算法(layer)
我們知道,一個(gè)N維的Cube,是由1個(gè)N維子立方體、N個(gè)(N-1)維子立方體、N*(N-1)/2個(gè)(N-2)維子立方體、…、N個(gè)1維子立方體和1個(gè)0維子立方體構(gòu)成,總共有2^N個(gè)子立方體組成,在逐層算法中,按維度數(shù)逐層減少來計(jì)算,每個(gè)層級(jí)的計(jì)算(除了第一層,它是從原始數(shù)據(jù)聚合而來),是基于它上一層級(jí)的結(jié)果來計(jì)算的。比如,[Group by A, B]的結(jié)果,可以基于[Group by A, B, C]的結(jié)果,通過去掉C后聚合得來的;這樣可以減少重復(fù)計(jì)算;當(dāng) 0維度Cuboid計(jì)算出來的時(shí)候,整個(gè)Cube的計(jì)算也就完成了。每一輪的計(jì)算都是一個(gè)MapReduce任務(wù),且串行執(zhí)行;一個(gè)N維的Cube,至少需要N次MapReduce Job。Cube逐層構(gòu)建算法
算法優(yōu)點(diǎn):
1)此算法充分利用了MapReduce的優(yōu)點(diǎn),處理了中間復(fù)雜的排序和shuffle工作,故而算法代碼清晰簡單,易于維護(hù);
2)受益于Hadoop的日趨成熟,此算法非常穩(wěn)定,即便是集群資源緊張時(shí),也能保證最終能夠完成。算法缺點(diǎn):
1)當(dāng)Cube有比較多維度的時(shí)候,所需要的MapReduce任務(wù)也相應(yīng)增加;由于Hadoop的任務(wù)調(diào)度需要耗費(fèi)額外資源,特別是集群較龐大的時(shí)候,反復(fù)遞交任務(wù)造成的額外開銷會(huì)相當(dāng)可觀;
2)由于Mapper邏輯中并未進(jìn)行聚合操作,所以每輪MR的shuffle工作量都很大,導(dǎo)致效率低下。
3)對(duì)HDFS的讀寫操作較多:由于每一層計(jì)算的輸出會(huì)用做下一層計(jì)算的輸入,這些Key-Value需要寫到HDFS上;當(dāng)所有計(jì)算都完成后,Kylin還需要額外的一輪任務(wù)將這些文件轉(zhuǎn)成HBase的HFile格式,以導(dǎo)入到HBase中去;總體而言,該算法的效率較低,尤其是當(dāng)Cube維度數(shù)較大的時(shí)候。
2)快速構(gòu)建算法(inmem)
也被稱作“逐段”(By Segment) 或“逐塊”(By Split) 算法,從1.5.x開始引入該算法,該算法的主要思想是,每個(gè)Mapper將其所分配到的數(shù)據(jù)塊,計(jì)算成一個(gè)完整的小Cube 段(包含所有Cuboid)。每個(gè)Mapper將計(jì)算完的Cube段輸出給Reducer做合并,生成大Cube,也就是最終結(jié)果。如圖所示解釋了此流程。Cube快速構(gòu)建法
與舊算法相比,快速算法主要有兩點(diǎn)不同:
1) Mapper會(huì)利用內(nèi)存做預(yù)聚合,算出所有組合;Mapper輸出的每個(gè)Key都是不同的,這樣會(huì)減少輸出到Hadoop MapReduce的數(shù)據(jù)量,Combiner也不再需要;
2)一輪MapReduce便會(huì)完成所有層次的計(jì)算,減少Hadoop任務(wù)的調(diào)配。
Cube存儲(chǔ)原理
Kylin Cube儲(chǔ)存原理

Kylin Cube構(gòu)建優(yōu)化
使用衍生維度(derived dimension)
衍生維度用于在有效維度內(nèi)將維度表上的非主鍵維度排除掉,并使用維度表的主鍵(其實(shí)是事實(shí)表上相應(yīng)的外鍵)來替代它們。Kylin會(huì)在底層記錄維度表主鍵與維度表其他維度之間的映射關(guān)系,以便在查詢時(shí)能夠動(dòng)態(tài)地將維度表的主鍵“翻譯”成這些非主鍵維度,并進(jìn)行實(shí)時(shí)聚合。
雖然衍生維度具有非常大的吸引力,但這也并不是說所有維度表上的維度都得變成衍生維度,如果從維度表主鍵到某個(gè)維度表維度所需要的聚合工作量非常大,則不建議使用衍生維度。概述:如果是衍生維度 一共4張表 一個(gè)是nomal 其余設(shè)置成derive 那么Cuboid就是7=2^3 -1
如果不設(shè)置成衍生維度就是=2^4-1=15
建議不適用衍生,雖然Cuboid小,但是數(shù)據(jù)你遲早要算
使用聚合組(Aggregation group)
聚合組(Aggregation Group)是一種強(qiáng)大的剪枝工具。聚合組假設(shè)一個(gè)Cube的所有維度均可以根據(jù)業(yè)務(wù)需求劃分成若干組(當(dāng)然也可以是一個(gè)組),由于同一個(gè)組內(nèi)的維度更可能同時(shí)被同一個(gè)查詢用到,因此會(huì)表現(xiàn)出更加緊密的內(nèi)在關(guān)聯(lián)。每個(gè)分組的維度集合均是Cube所有維度的一個(gè)子集,不同的分組各自擁有一套維度集合,它們可能與其他分組有相同的維度,也可能沒有相同的維度。每個(gè)分組各自獨(dú)立地根據(jù)自身的規(guī)則貢獻(xiàn)出一批需要被物化的Cuboid,所有分組貢獻(xiàn)的Cuboid的并集就成為了當(dāng)前Cube中所有需要物化的Cuboid的集合。不同的分組有可能會(huì)貢獻(xiàn)出相同的Cuboid,構(gòu)建引擎會(huì)察覺到這點(diǎn),并且保證每一個(gè)Cuboid無論在多少個(gè)分組中出現(xiàn),它都只會(huì)被物化一次。
對(duì)于每個(gè)分組內(nèi)部的維度,用戶可以使用如下三種可選的方式定義,它們之間的關(guān)系,具體如下。
1)強(qiáng)制維度(Mandatory),如果一個(gè)維度被定義為強(qiáng)制維度,那么這個(gè)分組產(chǎn)生的所有Cuboid中每一個(gè)Cuboid都會(huì)包含該維度。每個(gè)分組中都可以有0個(gè)、1個(gè)或多個(gè)強(qiáng)制維度。如果根據(jù)這個(gè)分組的業(yè)務(wù)邏輯,則相關(guān)的查詢一定會(huì)在過濾條件或分組條件中,因此可以在該分組中把該維度設(shè)置為強(qiáng)制維度。
2)層級(jí)維度(Hierarchy),每個(gè)層級(jí)包含兩個(gè)或更多個(gè)維度。假設(shè)一個(gè)層級(jí)中包含D1,D2…Dn這n個(gè)維度,那么在該分組產(chǎn)生的任何Cuboid中, 這n個(gè)維度只會(huì)以(),(D1),(D1,D2)…(D1,D2…Dn)這n+1種形式中的一種出現(xiàn)。每個(gè)分組中可以有0個(gè)、1個(gè)或多個(gè)層級(jí),不同的層級(jí)之間不應(yīng)當(dāng)有共享的維度。如果根據(jù)這個(gè)分組的業(yè)務(wù)邏輯,則多個(gè)維度直接存在層級(jí)關(guān)系,因此可以在該分組中把這些維度設(shè)置為層級(jí)維度。
3)聯(lián)合維度(Joint),每個(gè)聯(lián)合中包含兩個(gè)或更多個(gè)維度,如果某些列形成一個(gè)聯(lián)合,那么在該分組產(chǎn)生的任何Cuboid中,這些聯(lián)合維度要么一起出現(xiàn),要么都不出現(xiàn)。每個(gè)分組中可以有0個(gè)或多個(gè)聯(lián)合,但是不同的聯(lián)合之間不應(yīng)當(dāng)有共享的維度(否則它們可以合并成一個(gè)聯(lián)合)。如果根據(jù)這個(gè)分組的業(yè)務(wù)邏輯,多個(gè)維度在查詢中總是同時(shí)出現(xiàn),則可以在該分組中把這些維度設(shè)置為聯(lián)合維度。
這些操作可以在Cube Designer的Advanced Setting中的Aggregation Groups區(qū)域完成
聚合組的設(shè)計(jì)非常靈活,甚至可以用來描述一些極端的設(shè)計(jì)。假設(shè)我們的業(yè)務(wù)需求非常單一,只需要某些特定的Cuboid,那么可以創(chuàng)建多個(gè)聚合組,每個(gè)聚合組代表一個(gè)Cuboid。具體的方法是在聚合組中先包含某個(gè)Cuboid所需的所有維度,然后把這些維度都設(shè)置為強(qiáng)制維度。這樣當(dāng)前的聚合組就只能產(chǎn)生我們想要的那一個(gè)Cuboid了。
再比如,有的時(shí)候我們的Cube中有一些基數(shù)非常大的維度,如果不做特殊處理,它就會(huì)和其他的維度進(jìn)行各種組合,從而產(chǎn)生一大堆包含它的Cuboid。包含高基數(shù)維度的Cuboid在行數(shù)和體積上往往非常龐大,這會(huì)導(dǎo)致整個(gè)Cube的膨脹率變大。如果根據(jù)業(yè)務(wù)需求知道這個(gè)高基數(shù)的維度只會(huì)與若干個(gè)維度(而不是所有維度)同時(shí)被查詢到,那么就可以通過聚合組對(duì)這個(gè)高基數(shù)維度做一定的“隔離”。我們把這個(gè)高基數(shù)的維度放入一個(gè)單獨(dú)的聚合組,再把所有可能會(huì)與這個(gè)高基數(shù)維度一起被查詢到的其他維度也放進(jìn)來。這樣,這個(gè)高基數(shù)的維度就被“隔離”在一個(gè)聚合組中了,所有不會(huì)與它一起被查詢到的維度都沒有和它一起出現(xiàn)在任何一個(gè)分組中,因此也就不會(huì)有多余的Cuboid產(chǎn)生。這點(diǎn)也大大減少了包含該高基數(shù)維度的Cuboid的數(shù)量,可以有效地控制Cube的膨脹率。
Row Key優(yōu)化
Kylin會(huì)把所有的維度按照順序組合成一個(gè)完整的Rowkey,并且按照這個(gè)Rowkey升序排列Cuboid中所有的行。
設(shè)計(jì)良好的Rowkey將更有效地完成數(shù)據(jù)的查詢過濾和定位,減少IO次數(shù),提高查詢速度,維度在rowkey中的次序,對(duì)查詢性能有顯著的影響。Row key的設(shè)計(jì)原則如下:
1)被用作where過濾的維度放在前邊。
2)基數(shù)大的維度放在基數(shù)小的維度前邊。
并發(fā)粒度優(yōu)化
當(dāng)Segment中某一個(gè)Cuboid的大小超出一定的閾值時(shí),系統(tǒng)會(huì)將該Cuboid的數(shù)據(jù)分片到多個(gè)分區(qū)中,以實(shí)現(xiàn)Cuboid數(shù)據(jù)讀取的并行化,從而優(yōu)化Cube的查詢速度。具體的實(shí)現(xiàn)方式如下:構(gòu)建引擎根據(jù)Segment估計(jì)的大小,以及參數(shù)“kylin.hbase.region.cut”的設(shè)置決定Segment在存儲(chǔ)引擎中總共需要幾個(gè)分區(qū)來存儲(chǔ),如果存儲(chǔ)引擎是HBase,那么分區(qū)的數(shù)量就對(duì)應(yīng)于HBase中的Region數(shù)量。kylin.hbase.region.cut的默認(rèn)值是5.0,單位是GB,也就是說對(duì)于一個(gè)大小估計(jì)是50GB的Segment,構(gòu)建引擎會(huì)給它分配10個(gè)分區(qū)。用戶還可以通過設(shè)置kylin.hbase.region.count.min(默認(rèn)為1)和kylin.hbase.region.count.max**(默認(rèn)為500)兩個(gè)配置來決定每個(gè)Segment最少或最多被劃分成多少個(gè)分區(qū)。
由于每個(gè)Cube的并發(fā)粒度控制不盡相同,因此建議在Cube Designer 的Configuration Overwrites(上圖所示)中為每個(gè)Cube量身定制控制并發(fā)粒度的參數(shù)。假設(shè)將把當(dāng)前Cube的kylin.hbase.region.count.min設(shè)置為2,kylin.hbase.region.count.max設(shè)置為100。這樣無論Segment的大小如何變化,它的分區(qū)數(shù)量最小都不會(huì)低于2,最大都不會(huì)超過100。相應(yīng)地,這個(gè)Segment背后的存儲(chǔ)引擎(HBase)為了存儲(chǔ)這個(gè)Segment,也不會(huì)使用小于兩個(gè)或超過100個(gè)的分區(qū)。我們還調(diào)整了默認(rèn)的kylin.hbase.region.cut,這樣50GB的Segment基本上會(huì)被分配到50個(gè)分區(qū),相比默認(rèn)設(shè)置,我們的Cuboid可能最多會(huì)獲得5倍的并發(fā)量。

版權(quán)聲明:
文章不錯(cuò)?點(diǎn)個(gè)【在看】吧!??




