有一个数据多维分析的任务:

  • 日志的周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还是很远滴……

轻量级OLAP(一):Cube计算的更多相关文章

  1. 3D Cube计算引擎加速运算

    3D Cube计算引擎加速运算 华为达芬奇架构的AI芯片Ascend910,同时与之配套的新一代AI开源计算框架MindSpore. 为什么要做达芬奇架构? AI将作为一项通用技术极大地提高生产力,改 ...

  2. 轻量级OLAP(二):Hive + Elasticsearch

    1. 引言 在做OLAP数据分析时,常常会遇到过滤分析需求,比如:除去只有性别.常驻地标签的用户,计算广告媒体上的覆盖UV.OLAP解决方案Kylin不支持复杂数据类型(array.struct.ma ...

  3. Analysis Services OLAP 概述

    1. 什么是OLAP •定义1 :OLAP(联机分析处理)是针对特定问题的联机数据访问和分析.通过对信息(维数据)的多种可能的观察形式进行快速.稳定一致和交互性的存取,允许管理决策人员对数据进行深入观 ...

  4. SSAS——基础--cube

    SSAS——基础   一.Analysis Services Analysis Services是用于决策支持和BI解决方案的数据引擎.它提供报表和客户端中使用的分析数据. 它可在多用途数据模型中创建 ...

  5. 杂项-DB:OLAP(联机分析处理)

    ylbtech-杂项-DB:OLAP(联机分析处理) 联机分析处理OLAP是一种软件技术,它使分析人员能够迅速.一致.交互地从各个方面观察信息,以达到深入理解数据的目的.它具有FASMI(Fast A ...

  6. [转帖]OLTP、OLAP与HTAP

    OLTP.OLAP与HTAP https://blog.csdn.net/ZG_24/article/details/87854982   OLTP On-Line Transaction Proce ...

  7. OLAP(On-Line Analytical Processing)

    自20世纪80年代开始,许多企业利用关系型数据库来存储和管理业务数据,并建立相应的应用系统来支持日常的业务运作.这种应用以支持业务处理为主要目的,被称为联机事务处理(On line Transacti ...

  8. 星型数据仓库olap工具kylin介绍

    星型数据仓库olap工具kylin介绍 数据仓库是目前企业级BI分析的重要平台,尤其在互联网公司,每天都会产生数以百G的日志,如何从这些日志中发现数据的规律很重要. 数据仓库是数据分析的重要工具, 每 ...

  9. ORACLE的分组统计之CUBE(二)

    cube统计包含了rollup的统计结果,而且还有其他组合分组结果(小计),CUBE(n列),那么分组种类有: cube分组就是先进行合计(一个不取),然后小计(到),最后取标准分组. 与rollup ...

随机推荐

  1. XPath注入跟SQL注入差不多,只不过这里的数据库走的xml格式

    SQL注入这块不想细聊了,相信很多朋友都听到耳朵长茧,不外乎是提交含有SQL操作语句的信息给后端,后端如果没有做好过滤就执行该语句,攻击者自然可以随意操纵该站点的数据库. 比如有一个图书馆站点book ...

  2. windows和linux中搭建python集成开发环境IDE——如何设置多个python环境

    本系列分为两篇: 1.[转]windows和linux中搭建python集成开发环境IDE 2.[转]linux和windows下安装python集成开发环境及其python包 3.windows和l ...

  3. SQL Server 数据变更时间戳(timestamp)在复制中的运用

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 方案(Solution) 方案一(Solution One) 方案二(Solution Two ...

  4. Redis高可用分布式内部交流(九)

    这是上月在公司内部的一次分享,现把PPT及交流内容整理成博客. 阅读目录: 高可用 数据同步 分布式 分布式集群时代 总结 高可用 高可用(High Availability),是当一台服务器停止服务 ...

  5. MySQL LIST分区

    200 ? "200px" : this.width)!important;} --> 介绍 LIST分区和RANGE分区非常的相似,主要区别在于LIST是枚举值列表的集合, ...

  6. FTP文件服务搭建与同步传输

    需求       搭建一台FTP服务器,用于文件的上传与下载:同时将FTP服务器目录中的文件同步到多个服务器中,实现同步更新,同时文件需要控制用户访问对应的文件夹权限. 需要用到的软件有:bestsy ...

  7. Azure PowerShell (2) 修改Azure订阅名称

    <Windows Azure Platform 系列文章目录> Update: 2016-01-11 笔者文档主要都是用Azure PowerShell 0.x版本来实现的,比如0.98版 ...

  8. java中构造方法的特殊性

    构造方法名与类名相同 构造方法没有返回值,也不能写void 构造方法的主要作用是完成对对象的初始化工作 构造方法一般不由编程人员显示调用,而是由new来调用 在创建一个类的对象的同时,系统会自动调用该 ...

  9. 《Entity Framework 6 Recipes》中文翻译系列 (45) ------ 第八章 POCO之获取原始对象与手工同步对象图和变化跟踪器

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 8-6  获取原始对象 问题 你正在使用POCO,想从数据库获取原始对象. 解决方案 ...

  10. Atitit 动态调用webservice与客户端代理方式调用

    Atitit 动态调用webservice与客户端代理方式调用 方式1: 使用call.invoke  直接调用WSDL,缺点:麻烦,不推荐--特别是JAVA调用.NET的WS时,会有不少的问题需要解 ...