1. 程式人生 > >輕量級OLAP(一):Cube計算

輕量級OLAP(一):Cube計算

有一個數據多維分析的任務:

  • 日誌的周UV;
  • APP的收集量及標註量,TOP 20 APP(周UV),TOP 20 APP標註分類(周UV);
  • 手機機型的收集量及標註量,TOP 20 機型(周UV),TOP 20 手機廠商(周UV);

初始的解決方案:Spark讀取資料日誌,然後根據分析需求逐一進行map、distinct、reduceByKey得到分析結果。但是,這種方案存在著非常大的缺點——重複掃描資料來源多次。

1. Pig

Pig提供cube關鍵字做OLAP,將dimension分為了兩類:

  • normal,對應於cube operation,\(n\)個該維度的組合數為\(2^n\)
  • hierarchical ordering,對應於rollup operation, \(n\)
    個該維度的組合數為\(n+1\)

官方doc例子如下:

salesinp = LOAD '/pig/data/salesdata' USING PigStorage(',') AS
    (product:chararray, year:int, region:chararray, state:chararray, city:chararray, sales:long);
cubedinp = CUBE salesinp BY CUBE(product,year);
result = FOREACH cubedinp GENERATE FLATTEN(group), SUM(cube.sales) AS totalsales;

salesinp = LOAD '/pig/data/salesdata' USING PigStorage(',') AS
    (product:chararray, year:int, region:chararray, state:chararray, city:chararray, sales:long);
rolledup = CUBE salesinp BY ROLLUP(region,state,city);
result = FOREACH rolledup GENERATE FLATTEN(group), SUM(cube.sales) AS totalsales

在例子中,cube的操作相當於按維度組合對每一record進行展開並group by Dimensions,與下一句foreach語句構成了Dimensions + Measure的資料輸出格式。

2. Spark

樸素多維分析

從上面介紹的pig OLAP方案中,我們得到靈感——面對開篇的多維分析需求,也可以每一條記錄按Dimensions + Measure的規則進行展開:

/**
 * @param e (uid, LogFact)
 * @return Array[((dimension order No, dimension), measure)]
 */
def flatAppDvc(e: (String, CaseClasses.LogFact)): Array[((String, String), String)] = {
  val source = (("00", e._2.source), e._1)
  val appName = (("11", e._2.appName), e._1)
  val appTag = (("12", e._2.appTag), e._1)
  val appAll = (("13", "a"), e._1)
  val appCollect = (("14", "a"), e._2.appName)
  val appLabel = e._2.appTag match {
    case "EMPTY" => (("15", "a"), "useless")
    case _ => (("15", "a"), e._2.appName)
  }
  val dvcModel = (("21", e._2.dvcModelLabel), e._1)
  val vendor = (("22", e._2.vendor), e._1)
  val (osAll, osCollect) = ((("23", e._2.osType), e._1), (("24", e._2.osType), e._2.dvcModel))
  val osLabel = e._2.dvcModelLabel match {
    case "EMPTY" => (("25", e._2.osType), "useless")
    case _ => (("25", e._2.osType), e._2.dvcModel)
  }

  Array(source, appName, appTag, appAll, appCollect, appLabel, dvcModel, vendor,
    osAll, osCollect, osLabel).filter(_._2 != "useless")
}

為了區別不同的維度組合,程式碼中採取了比較low的方式——為每個維度組合進行編號以示區別。Spark提供flatMap API將一行展開為多行,完美地滿足了維度展開的需求;然後通過一把group by key + distinct count即可得到結果:

val flatRdd = logRdd.flatMap(flatAppDvc)
val result = flatRdd.distinct()
  .mapValues(_ => 1)
  .reduceByKey(_ + _)

多Measure

前面的分析需求比較簡單,measure均為distinct count;因而可以不必對齊Dimensions + Measure。然而,對於比較複雜的分析需求:

  • (整體上)廣告物料的收集量、標註量、PV;
  • (廣告物料的)二級標註類別的廣告物料數、UV、PV;
  • (廣告物料的)一級標註類別的廣告物料數、UV、PV;

measure既有distinct count (UV) 也有count (PV),這時需要Dimensions + Measure的對齊,維度flatMap如下:

/**
 * @param e ((adid, 2nd ad-category, 1st ad-category, uid)
 * @return Array[((dimension order No, dimension), measure:(adid, uid or adid, 1)]
 */
def flatAd(e: ((String, String, String), String)) = {
  val all = e._1._2 match {
    case "EMPTY" => (("0", "all"), (e._1._1, "non", 0))
    case _ => (("0", "all"), (e._1._1, e._1._1, 1))
  }
  val adCate = (("1", e._1._2), (e._1._1, e._2, 1))
  val adParent = (("2", e._1._3), (e._1._1, e._2, 1))

  Array(all, adCate, adParent)
}

爾後,計算每一維度的measure(其中distinct count採用HyperLogLogPlus演算法的stream lib實現):

val createHLL = (v: String) => {
  val hll = new HyperLogLogPlus(14, 0) // relative-SD = 0.01
  hll.offer(v)
  hll
}

def computeAdDimention(rdd: RDD[((String, String), (String, String, Int))]) = {
  rdd.combineByKey[(HyperLogLogPlus, HyperLogLogPlus, Int)](
    (v: (String, String, Int)) => (createHLL(v._1), createHLL(v._2), 1),
    (m: (HyperLogLogPlus, HyperLogLogPlus, Int), v: (String, String, Int)) => {
      m._1.offer(v._1)
      m._2.offer(v._2)
      val pv = m._3 + v._3
      (m._1, m._2, pv)
    },
    (m1: (HyperLogLogPlus, HyperLogLogPlus, Int),
     m2: (HyperLogLogPlus, HyperLogLogPlus, Int)) => {
      m1._1.addAll(m2._1)
      m1._2.addAll(m2._2)
      val pv = m1._3 + m2._3
      (m1._1, m1._2, pv)
    }
  )
    .mapValues(t => (t._1.cardinality().toInt, t._2.cardinality().toInt, t._3))
}

其實,本文有點標題黨~~只是借了OLAP的殼做資料多維分析,距離真正的OLAP還是很遠滴……

相關推薦

輕量級OLAPCube計算

有一個數據多維分析的任務: 日誌的周UV; APP的收集量及標註量,TOP 20 APP(周UV),TOP 20 APP標註分類(周UV); 手機機型的收集量及標註量,TOP 20 機型(周UV),TOP 20 手機廠商(周UV); 初始的解決方案:Spark讀取資料日誌,然後根據分析需求逐一進行map、

輕量級OLAPHive + Elasticsearch

1. 引言 在做OLAP資料分析時,常常會遇到過濾分析需求,比如:除去只有性別、常駐地標籤的使用者,計算廣告媒體上的覆蓋UV。OLAP解決方案Kylin不支援複雜資料型別(array、struct、map),要求資料輸入Schema必須是平鋪的,但是平鋪後丟失了使用者的聚合標籤資訊,而沒有辦法判斷某一個使用者

雲端計算學習筆記雲端計算基礎

本系列將對雲端計算進行學習,目前資料來自《雲端計算-概念、技術與架構》(第一作者:Tomas Erl)一書。目的是將書讀薄。這本書看了第一部分,翻譯怎麼說呢,偶碰網路上的詞不準確(極個別,不影響),可能是老師找學生翻譯的。語言有些生硬,譯者可能忠實原文,一對一進行了直譯,所有讀起來覺得不是中國人在說話,有

Openstack 雲計算 kvm 虛擬機配置

openstack kvm 虛擬化 Openstack 雲計算 (一): kvm 虛擬機配置

[python]My Unique JsonDiff演算法——如何計算2個json串之間的差距並Diff出來編輯距離Levenshtein演算法

    啊啊,年底忙著簽證什麼的,好久沒寫日誌啦。。。。新年到來,整點乾貨出來給大家~~順便為自己考試和申請學校攢點人品~~     之前實習的時候,因為實習公司的業務需求,需要一個比對json字串差異的演算法,然而我在網上查了很久的資料,發現竟然沒有現成

輕量級流程圖控制元件GoJS示例連載最小化

GoJS是一款功能強大,快速且輕量級的流程圖控制元件,可幫助你在JavaScript 和 HTML5 Canvas程式中建立流程圖,且極大地簡化你的JavaScript / Canvas 程式。 慧都網小編為大家準備了一套完整的GoJS的示例,將以連載的形式展開,供大家學習和交流討論。 這不是GoJS

No.23 經典筆試題用巨集來計算偏移量,判斷大小端聯合體法,指標法

寫一個巨集,計算結構體中某變數相對於首地址的偏移,並給出說明 判斷大小端 程式碼1: //寫一個巨集,計算結構體中某變數相對於首地址的偏移,並給出說明 //定義的這個巨集將結構體裡邊的變數的地址取出後再強轉成char型,然後進行相減。 //注意:&s ==

python裝飾器用法計算一個函式執行所需要的時間

import time from functools import wraps def time_this_function(func): #作為裝飾器使用,返回函式執行需要花費的時間

程式設計與數學計算玩家面對面

最近聽到這樣一個需求,VR多人遊戲的時候,當兩個玩家面對面的情況下,才可以開始下一個流程: 聽到一個人的解決方案是算距離,具體沒問,覺得略感複雜,趁此機會也發揮程式與數學的相關性一直很強,從此篇開始會專門寫一些程式與數學應用的部落格。 好了切入正題,每個角色

計算幾何凸包問題Convex Hull

### 引言 首先介紹下什麼是凸包?如下圖: ![](https://gitee.com//riotian/blogimage/raw/master/img/20200921200555.png) 在一個二維座標系中,有若干點雜亂排列著,將最外層的點連線起來構成的凸多邊型,它能包含給定的所有的點,這個多

工作流引擎Oozieworkflow

觸發 line last ssa pig oozie apt cnblogs 定時任務 1. Oozie簡介 Yahoo開發工作流引擎Oozie(馭象者),用於管理Hadoop任務(支持MapReduce、Spark、Pig、Hive),把這些任務以DAG(有向無環圖)方式

Spring 事務配置實戰過濾無需事務處理的查詢之類操作

log pla ssi pan spl tail gif aop img <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes

【SSH之旅】步步學習Hibernate框架關於持久化

stc localhost 對象 schema hbm.xml java let pass [] 在不引用不論什麽框架下,我們會通過平庸的代碼不停的對數據庫進行操作,產生了非常多冗余的可是又有規律的底層代碼,這樣頻繁的操作數據庫和大量的底層代碼的反復

CS231n基礎知識

深度學習 highlight 自己 元組 .py [0 upper bsp python 給自己新挖個坑:開始刷cs231n深度學習。 看了一下導言的pdf,差缺補漏。 s = "hello" print s.capitalize() # 首字母大寫; prints "

Javascript基礎簡單匯總元素獲取

問題 元素節點 all push 傳說 length [] nbsp 文檔 在頁面腳本中,如果要對頁面元素進行操作,那麽我們就要獲取到這個元素 那麽在獲取元素之前首先得要了解什麽是DOM(document object model) 在DOM,元素是以節點的形式表示的,每

elastic-job詳解數據分片

count 任務 不同的 應該 center shc 偶數 int ext 數據分片的目的在於把一個任務分散到不同的機器上運行,既可以解決單機計算能力上限的問題,也能降低部分任務失敗對整體系統的影響。elastic-job並不直接提供數據處理的功能,框架只會將分片項分配至各

中國mooc北京理工大學機器學習第二周分類

kmeans 方法 輸入 nump arr mod 理工大學 each orm 一、K近鄰方法(KNeighborsClassifier) 使用方法同kmeans方法,先構造分類器,再進行擬合。區別是Kmeans聚類是無監督學習,KNN是監督學習,因此需要劃分出訓練集和測試

在Python中用Request庫模擬登錄字幕庫無加密,無驗證碼

用戶名 com color 了無 1-1 value img requests log 如此簡單(不安全)的登錄表單已經不多見了。字幕庫的登錄表單如下所示,其中省去了無關緊要的內容: 1 <form class="login-form" action="/User/

Maven項目搭建Maven初體驗

測試類 java平臺 存在 ack 做的 rar cli maven2 試用 今天給大家介紹一個項目管理和綜合工具:Maven。 Maven: maven讀作 [‘meivin],本意是指可以被信任的領域專家,致力於傳播知識(來自於http://en.wikip

方便大家學習的Node.js教程理解Node.js

圖形 -1 iter pri attribute set run 相對 mage 理解Node.js 為了理解Node.js是如何工作的,首先你需要理解一些使得Javascript適用於服務器端開發的關鍵特性。Javascript是一門簡單而又靈活的語言,這種靈