基於 Kylin 的推薦系統效果評價系統

OLAP(聯機分析處理)是數據倉庫的主要應用之一,通過設計維度、度量,我們可以構建星型模型或雪花模型,生成數據多維立方體Cube,基於Cube可以做鑽取、切片、旋轉等多維分析操作。早在十年前,SQL Server、Oracle 等數據庫軟件就有OLAP產品,爲用戶提供關係數據庫、多維數據集、可視化報表的整套商業智能方案。 (本科畢業設計就是做OLAP分析,對相關理論和實踐有興趣的可以參閱我的論文,鏈接:https://share.weiyun.com/d6b7a9b521927d93c004efb9290ce8f1)

隨着大數據的發展,Kylin、Druid、Presto 等基於大數據的OLAP開源工具開始湧現,我們可以對億級的數據進行OLAP分析。Kylin 就是一款基於Hive的開源OLAP工具,我們可以設計Hive表的字段爲維度和度量,通過Kylin來構建Cube,Kylin會將Cube結構存儲在 HBase 之上,基於Cube我們可以做各種多維分析。在推薦系統開發過程中,我們往往需要按場景、策略、平臺等多個不同維度來比較效果數據,推薦系統的線上效果評價是一個很強的多維分析應用場景。因此,我們基於Kylin搭建了推薦系統效果評價系統。

本文主要包含三部分,首先介紹了我們的需求背景,其次介紹了Kylin的基本概念和原理,最後介紹了我們如何利用Kylin來完成推薦系統的效果評價。瞭解Kylin基礎的朋友可以直接閱讀第三部分,對Kylin原理較生疏的朋友建議先閱讀第二部分,尤其是Cube維度優化相關內容。

1 背景介紹

五八同城智能推薦系統是一個通用的推薦平臺,旨在爲五八同城不同業務線提供推薦服務。目前,我們接入了不同業務線在APP、PC、M三端上共計約六十個推薦位,包括大類頁、列表頁、詳情頁、公共頁(如APP首頁、消息中心頁等)等推薦場景。在一些核心推薦位上,我們會持續迭代召回策略、排序算法以及展示樣式,以不斷優化推薦效果。比較和分析不同業務線、不同推薦場景、不同推薦算法的效果是我們的基礎工作,早期我們是通過 Hive + MySQL的方式來實現效果數據的統計分析,但耗費了大量人力。在數據平臺提供了Kylin服務之後,我們基於Kylin重構了我們的推薦系統效果評價系統,大大節約了人力成本,提高了開發效率。

2 Apache Kylin基本原理和架構

Apache Kylin是一個開源的分佈式分析引擎,提供Hadoop之上的SQL查詢接口及多維分析(OLAP)能力以支持超大規模數據,能夠支持TB到PB級別的數據量,最初由eBay Inc開發並於2014年10月貢獻至開源社區,於2014年11月加入Apache孵化器項目,於2015年11月正式畢業成爲Apache 頂級項目。

2.1 名詞、概念解釋

事實表:事實表是用來記錄具體事件的,包含了每個事件的具體要素,以及具體發生的事情。

例如超市A的購物事實表:

時間         客戶id    商品id  數量   支付id

2016-10-11 10:52:30  2      3    1    1003

2016-10-11 10:52:30  2      4    2    1003

2016-10-11 12:31:10  2      2    2    1005

2016-10-11 12:31:10  2      4    1    1005

這張事實表記錄的其中一條事實爲:客戶id爲2的客戶在2016-10-11 10:52:30購買了1個商品id爲3的商品。

維表: 維表包含對事實表的某些列進行擴充說明的字段。例如超市A的商品維表:

商品id    商品名稱    商品單價

2       泡泡糖     1

3       泡麪      5

4       電池      2

事實表結合維表,可以得到更爲詳細的事實。當我們需要知道事實表中記錄的某個事實的更加詳細信息時,就需要使用對應的維表。

    星型模式: 包含一個或多個事實表、一組維表,以及事實表與維表的join方式。例如:

 度量: 度量是具體考察的聚合數量值,例如:銷售數量、銷售金額、人均購買量。計算機一點描述就是在SQL中就是聚合函數。

例如:select cate,count(1),sum(num) from fact_table where date>’20161112’ group by cate;

count(1)、sum(num)是度量

  維度: 維度是觀察數據的角度。例如:銷售日期、銷售地點。計算機一點的描述就是在SQL中就是where、group by裏的字段

例如:select cate,count(1),sum(num) from fact_table where date>’20161112’ group by cate;

date、cate是維度

預計算結果: 預計算結果是對事實表進行預計算的結果,預計算結果以鍵值對形式存在,鍵是維度的特定值、值是對應的度量值,一條預計算結果有一個對應的維度集合。例如商品銷售的預計算結果:

鍵值對<商品id=’2’,日期=’20161223’>:<數量=12,金額=21>是一條預計算結果,它對應的維度集合是{商品id, 日期},這條預計算結果表示商品id爲2的商品在20161223這一天總共賣出了12個,總價格爲21元。

鍵值對<商品id=’2’,日期=’20161223’,城市=’北京’>:<數量=8,金額=14>也是一條預計算結果。它對應的維度集合是{商品id, 日期, 城市},這條預計算結果表示商品id爲2的商品在20161223這一天的北京市總共賣出了8個,總價格爲14元。

鍵值對<>:<數量=100,金額=300>也是一條預計算結果。它對應的維度集合是空集,這條預計算結果表示歷史所有賣出的商品數量爲100個,總價格爲300元。

預計算結果全集:全部預計算結果組成的集合。

cuboid: 預計算結果全集中對應的維度集合相同的預計算結果的集合.

例:<商品id, 日期>cuboid是預計算結果全集中對應的維度子集等於{商品id, 日期}的預計算結果的集合。

數學一點的表示:<商品id, 日期>cuboid =

{預計算結果 | 預計算結果對應的維度子集={商品id, 日期},預計算結果∈預計算結果全集}

 cuboid樹:若干個不同的cuboid組成的有向樹,滿足孩子對應的維度集合是父親對應維度集合的子集

例如下面這兩棵cuboid樹:

Cube: Cube是一個集合,包含若干個cuboid。

2.2 Apache Kylin核心思想

簡單來說,Kylin的核心思想是預計算,用空間換時間,即對多維分析可能用到的度量進行預計算,將計算好的結果保存成Cube,供查詢時直接訪問。把高複雜度的聚合運算、多表連接等操作轉換成對預計算結果的查詢,這決定了Kylin能夠擁有很好的快速查詢和高併發能力。

2.3 Apache Kylin架構

kylin由以下幾部分組成:

· REST Server:提供一些restful接口,例如創建cube、構建cube、刷新cube、合併cube等cube的操作,project、table、cube等元數據管理、用戶訪問權限、系統配置動態修改等。除此之外還可以通過該接口實現SQL的查詢,這些接口一方面可以通過第三方程序的調用,另一方也被kylin的web界面使用。

· jdbc/odbc接口:kylin提供了jdbc的驅動,驅動的classname爲org.apache.kylin.jdbc.Driver,使用的url的前綴jdbc:kylin:,使用jdbc接口的查詢走的流程和使用RESTFul接口查詢走的內部流程是相同的。這類接口也使得kylin很好的兼容tebleau甚至mondrian。

· Query引擎:kylin使用一個開源的Calcite框架實現SQL的解析,相當於SQL引擎層。

· Routing:該模塊負責將解析SQL生成的執行計劃轉換成cube緩存的查詢,cube是通過預計算緩存在hbase中,這部分查詢是可以再秒級甚至毫秒級完成,而還有一些操作使用過查詢原始數據(存儲在hadoop上通過hive上查詢),這部分查詢的延遲比較高。

· Metadata:kylin中有大量的元數據信息,包括cube的定義,星型模型的定義、job的信息、job的輸出信息、維度的directory信息等等,元數據和cube都存儲在hbase中,存儲的格式是json字符串,除此之外,還可以選擇將元數據存儲在本地文件系統。

· Cube構建引擎:這個模塊是所有模塊的基礎,它負責預計算創建cube,創建的過程是通過hive讀取原始數據然後通過一些mapreduce計算生成Htable然後load到hbase中。

2.4 Kylin的Cube優化

計算Cube的存儲代價以及計算代價都是比較大的, 傳統OLAP的維度爆炸的問題Kylin也一樣會遇到。 Kylin提供給用戶一些優化措施,在一定程度上能降低維度爆炸的問題。

在業務分析中有許多cuboid是我們不會用到的。例如我們的推薦中我們不會分析沒有date維度的cuboid,就是說我們不會不指定日期來分析數據;我們在分析cuboid中帶recname的時候,就一定有scene,就是說我們在分析數據recname的時候,一定會同時分析scene。

我們可以不存儲也不計算這些我們不需要的cuboid。這樣就節省了很大的硬盤空間和Cube構建時間。這些都是Cube可以優化的空間。

Kylin的4種維度類型:

1.普通維度(General dimension):普通維度是不做任何優化的維度。有n個普通維度的Cube的cuboid的數量爲2^n

2.強制維度(Mandatory Dimensions):強制維度是Cube中所有cuboid中必有的維度。強制維度可以使Cube的cuboid減少一半。

3.層級維度(Hierarchy Dimensions),層級維度是有層次關係的維度,使得cuboid中低層次的維度總是伴隨着高層次維度的出現。一個有n個層次的層次維度可以使cuboid的數量從2^n降到n+1。例如 年、月、日 可以作爲3個層級的層級維度

4.組合維度(Joint Dimensions),組合維度是將幾個維度組合成一個維度,使得這幾個維度在cuboid中總是同時出現或總是同時不出現。一個有n個維度的組合維度可以使cuboid數量從2^n降到2。 例如 年、月、日 可以作爲有3個維度的組合維度(日期)。

Cube的cuboid數量計算例子:

普通維度數有n個,強制維度有m個,i個維度和j個維度的層級維度各一個,x個維度和y個維度的組合維度各一個的Cube。

普通維度有出現和不出現於cuboid中兩種情況,所以n個普通維度有2^n個不同的組合。

強制維度一定會出現在cuboid中,所以它不會使cuboid數目增加。

層級維度,在cuboid中低級的維度總是伴隨着高級的維度出現,所以i個維度和j個維度的層級維度各有(i+1)、(j+1)種不同的組合。

組合維度,組合維度中的維度總是同時出現/不出現在cuboid中,所以有y個維度的組合維度和有y個維度的組合維度各有2種不同的組合。

所以此Cube的Cuboid數量 =  (2^n)*(i+1)*(j+1)*2*2。

做Cube優化需要我們對自己的分析業務非常瞭解。不然可能會將我們需要cuboid去掉,導致查不出結果,或在查詢的時候引起不必要的較大的聚合使查詢過慢。

例如:

有2個維度date、cate,1個度量count(1) as pv。 不做任何優化的Cube X有所有的cuboid共2^2=4個,做了優化的的Cube Y 有 只有{date, cate }這個cuboid。在X上執行select count(1) from fact_table where ‘20161112’ = date

會直接在{date}這個cuboid上得到結果。 在Y上執行select count(1) from fact_table where ‘20161112’ = date。因爲Y沒有{date}這個cuboid,所以會發生聚合計算,將{date,cate}中的date=’20161112’的預查詢結果做聚合計算後返回結果

2.5 Kylin的distinct count聚合計算

Kylin中的度量,例如count、max、min、sum大部分我們都能理解是如何計算的,但count(distinct xxx)(UV)是如何計算的呢?

在Kylin有兩中方式計算UV:

第一種是 近似Count Distinct 。使用HyperLogLog算法實現了近似Count Distinct,提供了錯誤率從9.75%到1.22%幾種精度供選擇。算法計算後的Count Distinct指標,理論上,結果最大隻有64KB,最低的錯誤率是1.22%。這種實現方式用在需要快速計算、節省存儲空間,並且能接受錯誤率的Count Distinct指標計算。

第二種是 精準Count Distinct 。使用bitmap數據類型來做標記,雖然是bitmap類型,但不是真正的位圖,而是被當成了類似C++的bitset的數據結構。當數據類型爲int、short int、tiny等32位以內的數值型時,會直接映射到bitmap上,當數據類型爲long、string等其他類型時,會將數據值以字符串形式編成字典,在將字典上對應的字符串id映射到bitmap。這種實現方式提供了精確的無錯誤的Count Distinct結果,但是需要更多的存儲資源。 

2.6 Kylin的Cube構建

逐層算法是構建Cube的一種算法,它將cuboid按對應維度子集中緯度的個數分層。逐層計算cuboid,對維度個數較多的cuboid做聚合操作得到維度個數較少的cuboid。

假設我們有date、platform、algo三個維度,count(1) as pv、sum(num) as sumofnum兩個度量。不做任何的優化。事實集:

dateplatform    algo      num

20161213      android   13

20161214      ios     22

20161215      android   23

那麼cuboid樹爲:

因爲有4層,所以會做4次mapreducer計算。除了第一次mapreducer計算的輸入是源數據集外,其他每一次mapreducer計算的輸入輸出的每一行都是一條預計算結果。

第一次mapreducer將源數據集作爲輸入,計算並輸出第1層的cuboid {{date,platform,algo}},第二次的mapreducer以第一次的mapreducer的輸出做爲輸入,計算得出第二層的第2層的cuboid {{date,platform}, {date,algo}, {platform,algo}}。之後的mapreducer類似第二次的mapreducer。

map階段(除了第一次mapreducer的map),對於一行輸入,根據cuboid樹輸出對應的若干行,例如:

對於輸入:

<date=’20161213’,platform=’android’,algo=’1’>:<pv=1,sumofnum=3>

輸出:

<date=’20161213’,platform=’android’>:<pv=1,sumofnum=3>

<date=’20161213’,algo=’1’>:<pv=1,sumofnum=3>

<platform=’android’,algo=’1’>:<pv=1,sumofnum=3>

對於輸入:<date=’20161213’,algo=’1’>:<pv=1,sumofnum=3>

輸出:<date=’20161213’>:<pv=1,sumofnum=3>

reducer階段,將相同鍵的值做聚合操作,並輸出預計算結果,例如:

對於輸入:

<algo=’2’>:<pv=1,sumofnum=2>

<algo=’2’>:<pv=1,sumofnum=3>

輸出:<algo=’2’>:<pv=2,sumofnum=5>

除了逐層算法,還有快速Cube算法。該算法的主要思想是對Mapper所分配的數據塊,將它計算成一個完整的小Cube 段(包含所有Cuboid);每個Mapper將計算完的Cube段輸出給Reducer做合併,生成大Cube,也就是最終結果,這裏不在詳細介紹。

2.7 參考資料

http://blog.csdn.net/xiao_jun_0820/article/details/50731117

http://webdataanalysis.net/web-data-warehouse/data-cube-and-olap/

http://webdataanalysis.net/web-data-warehouse/multidimensional-data-model/

http://blog.csdn.net/rogerxi/article/details/3966782

http://www.cnblogs.com/en-heng/p/5239311.html

http://www.cnblogs.com/hark0623/p/5521006.html

http://lxw1234.com/archives/2016/08/712.htm

http://www.infoq.com/cn/articles/apache-kylin-algorithm/

3 如何利用 Kylin 完成推薦系統的效果評價

我們的推薦系統是一個通用的推薦平臺,爲五八同城不同業務線提供推薦服務。目前,接入了不同業務線在APP、PC、M三端上共計約六十個推薦位,包括大類頁、列表頁、詳情頁、公共頁(如APP首頁、消息中心頁等)等推薦場景。在一些核心推薦位上,我們會做AB Test多層實驗,持續迭代不同的召回、排序、展示方式,以優化推薦效果,如下圖所示:

       日常工作中,我們經常會比較不同業務線、不同客戶端、不同推薦位、不同推薦策略的數據效果,例如我們會比較房產和車在相同推薦位上的數據對比,猜你喜歡場景上不同排序算法的數據對比,二手房詳情頁在Android和IPhone上數據對比。各種數據對比能幫助我們優化推薦策略,甚至發現某些業務線功能邏輯上的隱藏BUG,例如在我們推薦項目攻堅階段,我們通過分析比較二手房詳情頁在Android和IPhone兩端的推薦效果,發現了IPhone上詳情頁瀏覽回退的BUG,最終反饋給業務方並解決了該問題,該BUG的解決使得我們在二手房的推薦點擊佔比絕對值提高了百分之一。總之,我們的推薦效果數據分析是一個很好的多維分析場景。

早期,我們的推薦效果數據統計是通過 MR + Hive + MySQL 來實現的,首先會從編寫MapReduce程序對原始埋點日誌進行抽取生成Hive表,然後會編寫大量的Hive SQL來統計各類指標數據,並將結果數據寫入MySQL數據表,最終做可視化展示和郵件報表。由於我們的比較維度多,比較指標多,Hive SQL語句的編寫消耗了我們不少人力。在數據平臺部門提供了Kylin服務支持後,我們將我們的效果數據統計工作遷移到了Kylin之上,我們只需要設計好Hive源數據表,並設置好維度和度量,Kylin便能根據維度和度量來自動預計算結果數據,這省去了我們編寫Hive SQL的工作,大大提高了效率。接入Kylin之後,我們的效果數據統計流程如下圖所示: 

Hive源數據表的設計

根據需求,維度和度量設計如下:

(1) 我們會從以下共計15個維度來做數據分析:

日期:比較不同日期的效果趨勢。

平臺:PC、M、APP(Android、IPhone)。

業務分類一級分類:如房產、車。

業務分類二級分類:如整租房、二手房;二手車、工程車。

推薦場景:如大類頁、列表頁、詳情頁、公共頁等。

推薦位:如二手車詳情頁同價位、同品牌推薦位。

排序算法號:不同的機器學習排序算法。

召回策略號:不同的召回方式。

前端展現號:在某個推薦場景下可能會同時ABTest兩種頁面樣式。

推薦規則號:例如在推薦邏輯的最後一步使用不同的去重規則或打散規則。

自定義維度:d1 ~d5,共五個擴展維度,以便於後續擴展。

(2) 我們的指標主要是點擊,需要統計的度量有:

點擊PV:詳情頁點擊量,稱作VPPV

點擊UV:詳情頁點擊用戶量

曝光PV:推薦位(一般是一個列表)曝光次數

曝光UV:推薦位曝光用戶量

曝光帖子數:推薦位上曝光的帖子數量。

基於這5個度量,會衍生出一些指標,例如我們關心的 點擊率、人均VPPV 等 ,以及一些中間指標如用戶點擊百分比、人均曝光帖子數、每次曝光帖子數等,這些中間指標很多人不關注,其實同樣重要,往往能幫助我們發現系統的一些問題。相關指標數據實例如下圖所示:

根據原始埋點所包含的信息以及我們設計的 維度和度量, 我們設計了 推薦點擊信息表和推薦曝光信息表兩張Hive寬表,這兩張Hive表中除了維度相關字段,還包括很多屬性字段。

推薦曝光信息表 主要字段如下:

CREATE EXTERNAL TABLE `gul_ext_58app_recommend_show`(

`imei` string,   // 用戶id

`numofshowinfoid` int,  // 曝光帖子數量

`seqno` string, // 曝光序列號

`timestamp` string, // 時間戳

.......,   // 各種屬性字段

`platform` string,       // 平臺

`cate_path1` string,  // 一級分類

`cate_path2` string,  // 二級分類

`recname` string,  // 推薦位

`algo` string,       //算法號

`recall` string,     // 召回號

`viewno` string,  // 展示號

`ruleno` string,   // 規則號

`d1` string,

`d2` string,

`d3` string,

`d4` string,

`d5` string)

PARTITIONED BY (

`date` string,    // 日期

`scene` string) //  推薦場景

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\u0001'

COLLECTION ITEMS TERMINATED BY '\u0002'

MAP KEYS TERMINATED BY '\u0003'

LINES TERMINATED BY '\n'

LOCATION

'/home/xxx/58app_recommend_show_for_hive';

    推薦點擊信息表 主要字段如下:

CREATE EXTERNAL TABLE `gul_ext_58app_recommend_click`(

`imei` string,     // 用戶id

`seqno` string,  // 點擊序列號

`timestamp` string, // 時間戳

`position` string,  // 點擊位置

`infoid` string,     // 點擊帖子id

......,   // 各種屬性字段

`platform` string,       // 平臺

`cate_path1` string,  // 一級分類

`cate_path2` string,  // 二級分類

`recname` string,  // 推薦位

`algo` string,       //算法號

`recall` string,     // 召回號

`viewno` string,  // 展示號

`ruleno` string,   // 規則號

`d1` string,

`d2` string,

`d3` string,

`d4` string,

`d5` string)

PARTITIONED BY (

`date` string,    // 日期

`scene` string) //  推薦場景

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\u0001'

COLLECTION ITEMS TERMINATED BY '\u0002'

MAP KEYS TERMINATED BY '\u0003'

LINES TERMINATED BY '\n'

LOCATION

'/home/xxx/58app_recommend_click_for_hive';

我們按日期、推薦場景對Hive表做分區。我們的數據一般以天爲單位,基本沒有查看一週或一月內的彙總數據(如周/月活躍用戶數)這種需求,所以按日期分區,kylin也只需構建不同日期的cube segment。由於APP Native埋點歷史遺留原因,部分推薦場景的埋點數據格式不統一,不同推薦場景的埋點格式可能不盡相同 (題外話:埋點設計是一項非常重要的工作,產品初期設計通用合理的埋點能爲後續工作節省大量的人力成本,後續我們將分享如何設計埋點) 。在我們的開發工作中,不同推薦場景是由不同的工程同事負責,工程同事需要負責埋點抽取工作,因此爲了方便不同工程同事獨立抽取各自場景下的埋點,我們將推薦場景也設計成分區。 (爲什麼不安排一個人來獨立完成抽取工作?這是因爲寫 ETL 程序是一個又苦又累的事情,而且技術含量不高,沒有這樣的人力來獨立完成該項工作,所以我們將工作分散至多人。)

如何將原始數據抽取至Hive數據表

值得一提的是,五八APP每天所有埋點數據都集中在HDFS上一個目錄下,數據非常龐大,而我們不同推薦場景下的埋點抽取都是一個獨立的MR作業,若每次都從原始數據抽取,將會消耗大量的集羣資源。因此,我們設計了一箇中間Hive表,採用兩個步驟得到最終的Hive數據表:第一步,基於曝光和點擊埋點的通用字段,運行一個MR作業解析原始埋點數據,得到中間表,其實是原始埋點的一個子集;第二步,基於中間表,多個MR抽取作業來解析不同場景的埋點,將結果數據追加至最終Hive數據表。這樣,便大大提高了抽取效率。抽取流程如下圖所示:

Kylin Cube 設計以及維度優化

基於Hive源數據表,我們創建了曝光和點擊兩個Cube。

(1) 點擊Cube:

事實表: 上述設計的 推薦點擊信息表  gul_ext_58app_recommend_click。

維表:沒有維表,直接利利用事實表中的字段做維度。

維度:date(日期)、scene(推薦場景)、platform(平臺)、cate_path1(一級分類)、cate_path2(二級分類)、recname(推薦位)、algo(算法號)、recall(觸發號)、viewno(展現號)、ruleno(規則號)、d1、d2、d3、d4、d5(擴展維度)。

度量:

    • count(1),即點擊PV;

    • count(distinct imei),即點擊UV。

Cube維度優化:

    • 強制維度:date      

    • 層級維度:

      • cate_path1→cate_path2   分類層級

      • scene→recname→algo    場景層級

    • 組合維度:(d1,d2,d3,d4,d5)

(2) 曝光Cube:

事實表: 上述設計的推薦曝光信息表  gul_ext_58app_recommend_show。

維度:和點擊Cube的維度相同。

度量:

    • count(1),即曝光PV;

    • count(distinct imei),即曝光UV。

    • sum(numofinfoid),即曝光帖子數。

Cube維度優化和點擊Cube維度優化相同。

維度優化很重要

下面我們來解釋一下曝光和點擊Cube的幾處優化:

第1處優化:我們在查詢數據時,總是會帶日期維度,所以我們將日期date作爲強制維度,這會使得Cube中的所有cuboid對應的維度集合都包含date,即所有的預查詢結果都包含date的特定值。

第2處優化:我們的業務分類是有層次關係的,二級分類 cate_path2 是一級分類 cate_path1 的下級,查詢時若cate_path2出現,cate_path1也會一併出現,所以我們將 cate_path1→cate_path2 設計爲一個二層的層級維度,這會使得Cube中所有的cuboid對應的維度集合在包含cate_path2的時候,必定也包含cate_path1。

第3處優化:在我們的業務中,推薦場景其實也有層次關係,算法號 algo 是推薦位 recname 的下級,推薦位 recname 是 推薦場景 scene的下級,因此,我們將 scene->recname->algo 設計爲一個三層的層級維度。

第4處優化:d1、d2、d3、d4、d5是自定義維度,是作爲擴展字段,實事表裏大部分數據這五個字段是空值,小部分數據這五個字段的其中某幾項有值。如果將他們作爲普通維度,那麼我們大約有 (2^5-1)/(2^5) = 31/32 的預查詢結果是無意義的,而將 (d1,d2,d3,d4,d5) 作爲組合維度的話,無意義的預查詢結果會降至約 (2^1-1)/(2^1) = 1/2,因此將(d1,d2,d3,d4,d5)作爲組合維度。這會使得Cube中所有cuboid對應的維度集合同時包含這5個維度或同時不包含這5個維度。在查詢那小部分自定義維度有意義的數據時,SQL中出現這五個維度中的某幾個,這會引起聚合計算,使得查詢變的稍慢,但我們認爲這是值得的,這算是在時間和空間中做的一個權衡。

經過這四處優化,我們的維度如下圖所示:

最終共包含4個普通維度、1個強制維度、1個層次爲2的層級維度、1個層次爲3的層級維度、1個維數爲5的組合維度。最終 cuboid的數量爲 (2^4)*1*(2+1)*(3+1)*2 = 384,而不做Cube優化的cuboid數量是 2^15 = 32768,可想而知,維度優化有多重要。

Kylin Cube 數據可視化

爲了直觀的查看推薦效果數據,我們還需要對效果數據進行可視化,以圖和表的形式展示數據。我們調研了一些開源可視化工具,部分不滿足我們的需求,部分部署麻煩,最後我們自主 開發了數據展示模塊。我們自主設計了前端頁面和後臺查詢接口,在後臺查詢接口中 調用了Kylin 的 REST API來獲取數據。下圖是一個可視化頁面實例。

4 總結和展望

本文主要介紹了Kylin的基本概念和原理,以及我們如何利用Kylin來完成推薦系統的效果評價。然而,當前是基於批量歷史數據的多維分析,我們的實時數據統計仍舊採用的是傳統的計算模式,下一步我們將接入實時多維分析。

後續我們將分享通用推薦平臺設計、個性化Push、機器學習通用特徵框架、埋點設計、大規模機器學習應用實踐方面的文章,敬請期待。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章