老生长谈的数据仓库 3 种建模方法,附猫眼娱乐数仓架构演进!
数据仓库存在的初期,甚至没有数据仓库的时候,猫眼的日常需求报表和数据接口提供方式如图一:
数据散落在企业各数据散落在企业各部门应用的数据存储中,它们之间有着复杂的业务连接关系,从整体上看就如一张巨大的蜘蛛网:结构上错综复杂,却又四通八达。在企业级数据应用上单一业务使用方便,且灵活多变;但涉及到跨业务、多部门联合应用就会存在:
-
数据来源多样化,管理决策数据过于分散;
-
数据缺乏标准,难以整合;
-
数据口径不统一,可信度低;
-
缺乏数据管控体系,数据质量根本无法保证。
从这种原始数据存储的方式提取数据,长期以往将会碰见以下问题:
-
数据缺乏可信性
-
数据越来越分散化
-
数据缺乏统一的标准,将失去数据准确性的意义
数据仓库的定义
数据仓库之父Bill Inmon在1991年出版的“Building the Data Warehouse”一书中所提出的定义被广泛接受:数据仓库(Data Warehouse)是一个面向主题的(Subject Oriented)、集成的(Integrated)、相对稳定的(Non-Volatile)、反映历史变化(Time Variant)的数据集合,用于支持管理决策(Decision Making Support)
-
面向主题的:普通的操作型数据库主要面向事务性处理,而数据仓库中的所有数据一般按照主题进行划分。主题是对业务数据的一种抽象,是从较高层次上对信息系统中的数据进行归纳和整理。面向主题的数据可以划分成两部分----根据原系统业务数据的特点进行主题的抽取和确定每个主题所包含的数据内容。例如用户主题、折扣卡主题、卖品主题、活动主题、财务主题等;分析数据仓库主题的时候,一般方法是先确定几个基本的主题,然后再将范围扩大,最后再逐步求精
-
集成性:面向操作型的数据库通常是异构的、并且相互独立,所以无法对信息进行概括和反映信息的本质。而数据仓库中的数据是经过数据的抽取、清洗、切换、加载得到的,所以为了保证数据不存在二义性,必须对数据进行编码统一和必要的汇总,以保证数据仓库内数据的一致性。数据仓库在经历数据集成阶段后,使数据仓库中的数据都遵守统一的编码规则,并且消除许多冗余数据。
-
稳定性:数据仓库中的数据反映的都是一段历史时期的数据内容,它的主要操作是查询、分析而不进行一般意义上的更新(数据集成前的操作型数据库主要完成数据的增加、修改、删除、查询),一旦某个数据进入到数据仓库后,一般情况下数据会被长期保留,当超过规定的期限才会被删除。通常数据仓库需要做的工作就是加载、查询和分析,一般不进行任何修改操作,是为了企业高层人员决策分析之用,(以上方法对于专资数据不太适用,专资数据总是存在部分影院延迟上报的问题)
-
反映历史变化:数据仓库不断从操作型数据库或其他数据源获取变化的数据,从而分析和预测需要的历史数据,所以一般数据仓库中数据表的键码(维度)都含有时间键,以表明数据的历史时期信息,然后不断增加新的数据内容。通过这些历史信息可以对企业的发展历程和趋势做出分析和预测。数据仓库的建设需要大量的业务数据作为积累,并将这些宝贵的历史信息经过加工、整理,最后提供给决策分析人员,这是数据仓库建设的根本目的。
数据仓库建模方法
实体建模法
实体建模并不是数据仓库建模中常见的一个方法,它来源于哲学的一个流派。从哲学的意义上说,客观世界应该是可以细分的,客观世界应该可以分成由一个个实体,以及实体与实体之间的关系组成。那么在数据仓库的建模过程中完全可以引入这个抽象的方法,将整个业务也可以划分成一个个的实体,而每个实体之间的关系,以及针对这些关系的说明就是我们数据建模需要做的工作。 虽然实体建模看起来好像有些抽象,其实理解起来很容易。即我们可以将任何一个业务划分成3个部分,实体,事件和说明。
image上图表述的是一个抽象的含义,如果描述一个简单的事实:“小明开车去学校上学”。以这个业务事实为例,我们可以把“小明”,“学校”看成是一个实体,“上学”描述成一个业务过程,在这里可以抽象为一个具体“事件”,而“开车去”怎可以看成事件“上学”的一个说明。
从上面列举的例子可以了解,我们使用的抽象归纳方法其实很简单,任何业务可以看成3个部分:
-
实体:指领域建模中特定的概念主题,指发生业务关系的对象;
-
事件:指概念主体之间完成一次业务流程的过程,指特定的业务过程;
-
说明:主要是针对实体和事件的特殊说明。
由于实体建模法,能够很轻松的实现业务建模的划分。因此,在业务建模阶段和领域建模阶段,实体建模方法有着广泛的应用。一般在没有现成的行业建模的情况下,可以采用实体建模的方法,和客户一起清理整个业务的模型,进行领域概念的划分,抽象出具体的业务概念,结合客户的使用特点,完全可以创建出一个符合自己需要的数据仓库模型来。 但是,实体建模也有着自己先天的缺陷,由于实体说明法只是一种抽象客观事件的方法,因此,注定了该建模方法只能局限在业务建模和领域概念建模阶段。因此,到了逻辑建模阶段和物理建模阶段,则是范式建模和维度建模发挥长处的阶段。
范式建模法
范式建模法其实是我们在构建数据模型常用的一个方法,该方法的主要由inmon所提倡,主要解决关系型数据库中数据存储,利用的一种技术层面上的方法。目前,在关系型数据库中的建模方法,大部分采用的是三范式建模法。 范式是数据库逻辑模型设计的基本理论,一个关系模型可以从第一范式到第三范式进行无损分解,这个过程也可以称为规范化。在数据仓库的模型设计中目前一般采用第三范式,他有着严格的数学定义。从其表达的含义来看,一个符合第三范式的关系必须具有以下三个条件:
-
每个属性值唯一,不具有多义性;
-
每个非主属性必须完全依赖于整个主键,而非主键的一部分;
-
每个非主属性不能依赖于其他关系中的属性,因为这样的话,这种属性应该归到其他关系中去。
根据Inmon的观点,数据仓库模型的建设方法和业务系统的企业数据模型类似。在业务系统中,企业数据模型决定了数据的来源,而企业数据模型也分为两个层次,即主题域模型和逻辑模型。同样,主题域模型可以看成业务模型的概念模型,而逻辑模型则是域模型在关系型数据库上的实例化。
image从业务数据模型转向数据仓库模型时,同样也需要有数据仓库的域模型,即概念模型,同时也存在域模型的逻辑模型。这里,业务模型中的数据模型和数据仓库的模型稍稍有一些不同,主要区别在于:
-
数据仓库的域模型应该包含企业数据模型的域模型之间的关系,以及各个域模型定义。数据仓库的域模型的概念应该比业务系统的主题域模型规范更加广。
-
在数据仓库的逻辑模型需要从业务系统的数据模型中的逻辑模型中抽象实体,实体的属性,实体的子类,以及实体的关系等。
范式建模法的最大优点就是从关系型数据库的角度出发,结合了业务系统的数据模型,能够比较方便的实现数据仓库的建模。但其缺点也很明显,由于建模方法限定在关系型数据库之上,在某些时候反而限制了整个数据仓库模型的灵活性,性能等,特别是考虑数据仓库的底层数据向数据集市的数据进行汇总时,需要进行一定的变通才能满足响应的需求。
维度建模法
维度建模法,是Kimball最先提出的概念,将数据抽象为事实表与维度表两种,而根据二者之间的关系将整体的模型划分为星型模型与雪花模型两种。这种建模方法的优势在于,根据各个维度对数据进行了预处理,比如按照时间维度进行预先的统计、分类等等,可以提高数据分析应用时的效率,是适于分析的一种方法。具体来看看几个概念:
-
维度表与事实表。维度表,描述的是事物的属性,反映了观察事物的角度。事实表,描述的是业务过程的事实数据,是要关注的具体内容,每行数据对应一个或多个度量事件。比如,分析“某地区某商品某季度的销量”,就是从地区、商品、时间(季度)三个角度来观察商品的销量,维度表有地区表、商品表和时间表,事实表为销量表。在销量表中,通过键值关联到三个维度表中,通过度量值来表示对应的销量,因此事实表通常有两种字段:键值列、度量值列。
-
星型模型与雪花模型。两种模型表达的是事实表与维度表之间的关系。当所有需要的维度表都直接关联到事实表时,看上去就是一颗星星,称之为星型模型;当有一个或多个维表没有直接关联到到事实表上,而是通过其他维度表连接到事实表上时,看上去就是一颗雪花,称之为雪花模型。二者的区别在于,雪花模型一定程度上降低了信息冗余度,但是合适的冗余信息能有效的帮助我们提高查询效率。
- 基本的维度建模思路。维度建模的基本思路可以归纳为这么几点:第一,确定主题,即搞清楚要分析的主题是什么,比如上述的“某地区某商品某季度的销量”;第二,确定分析的维度,准备从哪几个角度来分析数据;第三,确定事实表中每行的数据粒度,比如时间粒度细化到季度就可以了;第四,确定分析的度量事件,即数据指标是什么。
举个例子,业务场景是:一款做连锁企业招聘工作的产品,比如为麦当劳的所有连锁门店招聘员工,现在要分析“每家门店的招聘情况如何?”。结合具体业务,我们引入六个维度:时间维度、地区维度、品牌维度、门店维度、职位维度、申请渠道;数据指标上,主要有申请工作人数、申请工作次数、聘用人数、拒绝人数,每个指标分别有增量值和总量值两种;数据粒度上,时间维度细分到以小时为单位,地区维度细分到市一级。下图所示便是相应的星型模型,有三点值得一提:
可以看到我们只建立了四张维度表,地区维度和渠道维度是直接以字符串的形式放到事实表中的。这是维度设计中经常遇到的一个问题:如果这个维度只有一个属性,那么是作为单独的一张表还是作为事实表的一部分?其实并没有完全对与错的答案,只有是否适合自己的答案。这里,城市与渠道的信息并不会发生变化,所以放入事实表中可以避免联合查询。
建立了统一的时间维度,可以支持各种时间统计方案,避免在查询时进行时间值运算。
在品牌维度、门店维度、职位维度三张表中,都有prod_xxxx_id的字段,其值是产品业务数据库中相应数据的id,作用是为了与业务数据库中的信息进行同步。当业务数据库中的相关信息发生变化时,会通过ETL来更新数据仓库中的信息,因此我们需要这样的一个字段来进行唯一标识。
image数仓在维度建模层次划分
经过长时间的探索,在物理建模这个过程中一般会进行层次划分,分别是:基础事实、轻度汇总层、集市宽表层。
image-
基础事实层(detail):基础层的数据粒度比较细,通常与ods层的粒度相似,只是在ods数据的基础上做了清洗、规范化和为了方便分析而作的一些整合,有可能需要结合维度表。
-
轻度汇总层(aggr):汇总层是根据各集市的数据需求,抽象出比较通用的数据,对明细层按照一些统计偏向(例如:口径、业务方向)进行汇总得到。
-
集市款表层(topic):集市宽表主要是在轻度汇总层的基础之上创建,由于轻度汇总层的数据有所偏向,所以按照这些事实表的粒度和公共维度,通过更高等级的视图将它们整合起来
-
维度表:包括直接从业务方同步的维度表、根据事实表整理成的维度表以及直接生成的维度表等。
猫眼的数据仓库建设的发展史
阶段一:
2015年的猫眼初步建设数据仓库的时候,以快速满足业务需求为主,为了尽快达到数据展示效果,多数需求以烟筒式开发为主,针对每个需求的特点,独立开发每个需求,需求之间没有关联,没有交互,没有复用,底层数据表结构调整后,数据测修改的更多。运维成本出奇的高,随时时间的推移,数据存在不一致性。
image阶段二:
针对阶段一的猫眼数据仓库的缺点,后期升级猫眼离线数据仓库,针对一的缺点,我们发现需求方多来自同一个业务,比如选座,折扣卡,券码等产品或者运营。
我们按照业务方的特点,建设以业务为主题的数据仓库模型,改变同一业务无法复用数据,改变同一业务数据一致性的
image阶段三
面向模型开发,针对不同业务,怎么解决同名同义性,异名异议性,以及如何解决数据孤岛的问题,我们提出用模型解决,前期我们将从订单模型,UGC模型,以及支付模型,财务模型出发,统一同源数据,统一公司口径,统一数据生成出口
image