-----------------------------------------------------分隔符-----------------------------------------------------
数据仓库之电商数仓-- 1、用户行为数据采集==>
数据仓库之电商数仓-- 2、业务数据采集平台==>
数据仓库之电商数仓-- 3.1、电商数据仓库系统(DIM层、ODS层、DWD层)==>
数据仓库之电商数仓-- 3.2、电商数据仓库系统(DWS层)==>
数据仓库之电商数仓-- 3.3、电商数据仓库系统(DWT层)==>
数据仓库之电商数仓-- 3.4、电商数据仓库系统(ADS层)==>
数据仓库之电商数仓-- 4、可视化报表Superset==>
数据仓库之电商数仓-- 5、即席查询Kylin==>
Apache Kylin是一个开源的分布式分析引擎
,提供Hadoop/Spark之上的SQL查询接口及多维分析(OLAP)
能力以支持超大规模数据,最初由eBay Inc开发并贡献至开源社区。它能在亚秒内查询巨大的Hive表。
各种数据
(包括历史数据和当前数据)的中心存储系统,是BI(business intelligence, 商业智能)的核心部件;此处的数据包括企业业务系统的订单、库存、交易账目、客户和供应商等来自企业所处行业和竞争对手的数据以及来自企业所处的其他外部环境中的各种数据。
数据转化为知识
,帮助企业做出明智的业务经营决策的工具;为了将数据转化为知识,需要利用数据仓库、联机分析处理(OLAP)工具和数据挖掘等技术。
从各个方面观察信息
,以达到深入理解数据的目的。多维分析
。注⚠️:一个Cube可以包含多个Cuboid!
REST Server是一套面向应用程序开发的入口点,旨在实现针对Kylin平台的应用开发工作。 此类应用程序可以提供查询、获取结果、触发cube构建任务、获取元数据以及获取用户权限等等。另外可以通过Restful接口实现SQL查询。
当cube准备就绪后,查询引擎就能够获取并解析用户查询。它随后会与系统中的其它组件进行交互,从而向用户返回对应的结果。
在最初设计时曾考虑过将Kylin不能执行的查询引导去Hive中继续执行,但在实践后发现Hive与Kylin的速度差异过大,导致用户无法对查询的速度有一致的期望,很可能大多数查询几秒内就返回结果了,而有些查询则要等几分钟到几十分钟,因此体验非常糟糕。最后这个路由功能在发行版中默认关闭。
Kylin是一款元数据驱动型应用程序。元数据管理工具是一大关键性组件,用于对保存在Kylin当中的所有元数据进行管理,其中包括最为重要的cube元数据。其它全部组件的正常运作都需以元数据管理工具为基础。 Kylin的元数据存储在hbase中。
这套引擎的设计目的在于处理所有离线任务,其中包括shell脚本、Java API以及Map Reduce任务等等。任务引擎对Kylin当中的全部任务加以管理与协调,从而确保每一项任务都能得到切实执行并解决其间出现的故障。
Kylin的主要特点包括支持SQL接口、支持超大规模数据集、亚秒级响应、可伸缩性、高吞吐率、BI工具集成等。
安装Kylin前需先部署好Hadoop、Hive、Zookeeper、HBase
,并且需要在/etc/profile
中配置以下环境变量HADOOP_HOME,HIVE_HOME,HBASE_HOME
,记得source使其生效。
(base) [xiaobai@hadoop102 kylin]$ tar -zxvf apache-kylin-3.0.2-bin.tar.gz -C /opt/module/
(base) [xiaobai@hadoop102 module]$ mv apache-kylin-3.0.2-bin/ kylin
修改/opt/module/kylin/bin/find-spark-dependency.sh
,排除冲突的jar包
需要增加的内容:! -name '*jackson*' ! -name '*metastore*'
(base) [xiaobai@hadoop102 bin]$ vim find-spark-dependency.sh
Hadoop(hdfs,yarn,jobhistoryserver)、Zookeeper、Hbase
;⭐️(base) [xiaobai@hadoop102 kylin]$ bin/kylin.sh start
(base) [xiaobai@hadoop102 logs]$ jps
17056 QuorumPeerMain
20928 RunJar
67456 HRegionServer
77760 RunJar
16883 JobHistoryServer
16277 DataNode
16662 NodeManager
16126 NameNode
67103 HMaster
78110 Jps
[xiaobai@hadoop103 ~]$ jps
111509 NodeManager
116933 HRegionServer
118357 Jps
10325 Kafka
111924 QuorumPeerMain
111371 ResourceManager
111151 DataNode
[xiaobai@hadoop104 module]$ jps
82260 NodeManager
82153 SecondaryNameNode
82440 QuorumPeerMain
86856 Jps
85836 HRegionServer
停止kylin:
(base) [xiaobai@hadoop102 kylin]$ bin/kylin.sh stop
以gmall数据仓库中的dwd_order_detail作为事实表,dim_user_info、dim_sku_info、dim_base_province作为维度表,构建星型模型,并演示如何使用Kylin进行OLAP分析。
点击加号,创建工程,填写项目名称和描述信息,submit提交。
注⚠️:
Kylin不能处理Hive表中的复杂数据类型(Array,Map,Struct),即便复杂类型的字段并未参与到计算之中。故在加载Hive数据源时,不能直接加载带有复杂数据类型字段的表。而在dim_sku_info表中存在两个复杂数据类型的字段(平台属性和销售属性),故dim_sku_info不能直接加载,需对其进行以下处理。
hive (gmall)>
create view dim_sku_info_view
as
select
id,
price,
sku_name,
sku_desc,
weight,
is_sale,
spu_id,
spu_name,
category3_id,
category3_name,
category2_id,
category2_name,
category1_id,
category1_name,
tm_id,
tm_name,
create_time
from dim_sku_info;
虚拟机承受不起了 创建model/ 创建Cube略 后续有机会再搞;
维度:即观察数据的角度
。如员工数据,可从性别角度来分析,也可更加细化,从入职时间或地区等的维度来观察。维度是一组离散的值,如性别中的男女,或时间维度上的每一个独立的日期。
因此在统计时可以将维度值相同的记录聚合在一起,然后应用聚合函数作累加、平均、最大和最小值等聚合计算;
度量:即被聚合(观察)的统计值,也就是聚合运算的结果。
如员工数据中不同性别员工的个数,或在同一年入职的员工人数。
有了维度跟度量,一个数据表或者数据模型上的所有字段就可以分类了,它们要么是维度,要么是度量(可以被聚合)。于是就有了根据维度和度量做预计算的Cube理论
。
给定一个数据模型,我们可以对其上的所有维度进行聚合,对于N个维度来说,组合的所有可能性共有2n种。
对于每一种维度的组合,将度量值做聚合计算,然后将结果保存为一个物化视图,称为Cuboid
。所有维度组合的Cuboid作为一个整体,称为Cube
。
:
假设有一个电商的销售数据集,其中维度包括时间[time]、商品[item]、地区[location]和供应商[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种。
❗️每一种维度组合就是一个Cuboid,16个Cuboid整体就是一个Cube。
我们知道,一个N维的Cube,是由1个N维子立方体、N个(N-1)维子立方体、N*(N-1)/2个(N-2)维子立方体、…、N个1维子立方体和1个0维子立方体构成,总共有2N个子立方体组成,在逐层算法中,按维度数逐层减少来计算,每个层级的计算(除了第一层,它是从原始数据聚合而来),是基于它上一层级的结果来计算的
。比如,[Group by A, B]的结果,可以基于[Group by A, B, C]的结果,通过去掉C后聚合得来的;这样可以减少重复计算;当 0维度Cuboid计算出来的时候,整个Cube的计算也就完成了。
❗️每一轮的计算都是一个MapReduce任务,且串行执行;一个N维的Cube,至少需要N次MapReduce Job。
❗️总体而言,该算法的效率较低,尤其是当Cube维度数较大的时候。
也被称作“逐段”(By Segment) 或“逐块”(By Split) 算法,从1.5.x开始引入该算法,该算法的主要思想是,每个Mapper将其所分配到的数据块,计算成一个完整的小Cube 段(包含所有Cuboid)。每个Mapper将计算完的Cube段输出给Reducer做合并,生成大Cube,也就是最终结果。如图所示解释了此流程。
预聚合
,算出所有组合;Mapper输出的每个Key都是不同的,这样会减少输出到Hadoop MapReduce的数据量,Combiner也不再需要;衍生维度用于在有效维度内将维度表上的非主键维度排除掉,并使用维度表的主键(其实是事实表上相应的外键)来替代它们
。Kylin会在底层记录维度表主键与维度表其他维度之间的映射关系,以便在查询时能够动态地将维度表的主键“翻译”成这些非主键维度,并进行实时聚合。
简单来说,就是说某个维度若采用衍生维度,参与最终聚合计算的不是改衍生维度,而是此衍生维度所在维度表的主键。
❗️虽然衍生维度具有非常大的吸引力,但这也并不是说所有维度表上的维度都得变成衍生维度,如果从维度表主键到某个维度表维度所需要的聚合工作量非常大,则不建议使用衍生维度。
此处的工作量大具体指若主键与维度相差10倍以上则算大。
聚合组(Aggregation Group) 是一种强大的剪枝工具
。聚合组假设一个Cube的所有维度均可以根据业务需求划分成若干组(当然也可以是一个组),由于同一个组内的维度更可能同时被同一个查询用到,因此会表现出更加紧密的内在关联。每个分组的维度集合均是Cube所有维度的一个子集,不同的分组各自拥有一套维度集合,它们可能与其他分组有相同的维度,也可能没有相同的维度。每个分组各自独立地根据自身的规则贡献出一批需要被物化的Cuboid,所有分组贡献的Cuboid的并集就成为了当前Cube中所有需要物化的Cuboid的集合。不同的分组有可能会贡献出相同的Cuboid,构建引擎会察觉到这点,并且保证每一个Cuboid无论在多少个分组中出现,它都只会被物化一次。
对于每个分组内部的维度,用户可以使用如下三种可选的方式定义,它们之间的关系,具体如下。
如果一个维度被定义为强制维度,那么这个分组产生的所有Cuboid中每一个Cuboid都会包含该维度
。每个分组中都可以有0个、1个或多个强制维度。如果根据这个分组的业务逻辑,则相关的查询一定会在过滤条件或分组条件中,因此可以在该分组中把该维度设置为强制维度。
则多个维度直接存在层级关系,因此可以在该分组中把这些维度设置为层级维度
。❗️若A->B为层级维度,从0到n的维度中,从A开始到C、AB、AC、ABC,B直接作为A的下一个层级,不在同一级出现,ABC作为AB的下一层级。
这些联合维度要么一起出现,要么都不出现
。每个分组中可以有0个或多个联合,但是不同的联合之间不应当有共享的维度(否则它们可以合并成一个联合)。如果根据这个分组的业务逻辑,多个维度在查询中总是同时出现,则可以在该分组中把这些维度设置为联合维度
。
聚合组的设计非常灵活,甚至可以用来描述一些极端的设计。假设我们的业务需求非常单一,只需要某些特定的Cuboid,那么可以创建多个聚合组,每个聚合组代表一个Cuboid。具体的方法是在聚合组中先包含某个Cuboid所需的所有维度,然后把这些维度都设置为强制维度。这样当前的聚合组就只能产生我们想要的那一个Cuboid了。
再比如,有的时候我们的Cube中有一些基数非常大的维度,如果不做特殊处理,它就会和其他的维度进行各种组合,从而产生一大堆包含它的Cuboid。包含高基数维度的Cuboid在行数和体积上往往非常庞大,这会导致整个Cube的膨胀率变大。如果根据业务需求知道这个高基数的维度只会与若干个维度(而不是所有维度)同时被查询到,那么就可以通过聚合组对这个高基数维度做一定的“隔离”。
我们把这个高基数的维度放入一个单独的聚合组,再把所有可能会与这个高基数维度一起被查询到的其他维度也放进来。这样,这个高基数的维度就被“隔离”在一个聚合组中了,所有不会与它一起被查询到的维度都没有和它一起出现在任何一个分组中,因此也就不会有多余的Cuboid产生。这点也大大减少了包含该高基数维度的Cuboid的数量,可以有效地控制Cube的膨胀率。
Kylin会把所有的维度按照顺序组合成一个完整的Rowkey,并且按照这个Rowkey升序排列Cuboid中所有的行。
设计良好的Rowkey将更有效地完成数据的查询过滤和定位,减少IO次数,提高查询速度,维度在rowkey中的次序,对查询性能有显著的影响。