数据仓库——维度建模

在维度建模中,将度量称为“事实”,将环境描述为“维度”

维度表

维度表概念

维度是维度建模的基础和灵魂。在维度建模中,将度量称为“事实”,将环境描述为“维度”,维度是用于分析事实所需要的多样环境。

例如,在分析交易过程时,可以通过买家、卖家、商品和时间等维度描述交易发生的环境。 维度所包含的表示维度的列,称为维度属性。维度属性是查询约束条件、分组和报表标签生成的基本来源,是数据易用性的关键。

例如,在查询请求中,获取某类目的商品、正常状态的商品等,是通过约束商品类目属性和商品状态属性来实现的;统计淘宝不同商品类目的每日成交金额,是通过商品维度的类目属性进行分组的;我们在报表中看到的类目、BC类型(B指天猫,C指集市)等,都是维度属性。所以维度的作用一般是查询约束、分类汇总以及排序等。 维度表特征

维度表的范围很宽(具有多个属性、列比较多)跟事实表相比,行数较少,(通常小于10万条)内容相对固定

维度表设计原则

维度属性尽量丰富,为数据使用打下基础

比如淘宝商品维度有近百个维度属性,为下游的数据统计、分析、探查提供了良好的基础。 给出详实的、富有意义的文字描述

属性不应该是编码,而应该是真正的文字。在间里巴巴维度建模中, 一般是编码和文字同时存在,比如商品维度中的商品 ID 和商品标题、 类目 ID 和 类目名称等。 ID 一 般用于不同表之间的关联,而名称一般用 于报表标签 区分数值型属性和事实

数值型宇段是作为事实还是维度属性,可以参考字段的一般用途。 如果通常用于查询约束条件或分组统计,则是作为维度属性;如果通常 用于参与度量的计算,则是作为事实。比如商品价格,可以用于查询约 束条件或统计价格区间 的商品数量,此时是作为维度属性使用的;也可 以用于统计某类目 下商品的平均价格,此时是作为事实使用的。另外, 如果数值型字段是离散值,则作为维度属性存在的可能性较大;如果数 值型宇段是连续值 ,则作为度量存在的可能性较大,但并不绝对,需要 同时参考宇段的具体用途。 沉淀出通用的维度属性,为建立一致性维度做好铺垫

有些维度属性获取需要进行比较复杂的逻辑处理,有些需要通过多表关联得到,或者通过单表 的不同宇段混合处理得到,或者通过对单表 的某个字段进行解析得到。此时,需要将尽可能多的通用的维度属性进 行沉淀。一方面,可以提高下游使用的方便性,减少复杂度;另一方面,可以避免下游使用解析时由于各自逻辑不同而导致口径不一致。 退化维度(DegenerateDimension)

在维度类型中,有一种重要的维度称作为退化维度。这种维度指的是直接把一些简单的维度放在事实表中。退化维度是维度建模领域中的一个非常重要的概念,它对理解维度建模有着非常重要的作用,退化维度一般在分析中可以用来做分组使用。 缓慢变化维(Slowly Changing Dimensions)

维度的属性并不是始终不变的,它会随着时间的流逝发生缓慢的变化,这种随时间发生变化的维度我们一般称之为缓慢变化维(SCD),缓慢变化维一般使用代理健作为维度表的主健。处理方式:

直接覆盖原值 – 不看历史数据,简单粗暴

拉链表 – 需要在维度行再增加三列:有效日期、截止日期、行标识(可选)。

增加属性列 - 冗余维度:

为了提升效率,把常用的维度冗余到事实表

维度设计方法

维度的设计过程就是确定维度属性的过程,如何生成维度属性,以及所生成的维度属性的优劣,决定了维度使用的方便性,成为数据仓库易用性的关键。正如Kimball所说的,数据仓库的能力直接与维度属性的质量和深度成正比。下面以淘宝的商品维度为例对维度设计方法进行详细说明。

第一步:选择维度或新建维度。作为维度建模的核心,在企业级数据仓库中必须保证维度的唯一性。以淘宝商品维度为例,有且只允许有一个维度定义。第二步:确定主维表。此处的主维表一般是ODS表,直接与业务系统同步。以淘宝商品维度为例,s_auction_ auctions是与前台商品中心系统同步的商品表,此表即是主维表。第三步:确定相关维表。数据仓库是业务源系统的数据整合,不同业务系统或者同一业务系统中的表之间存在关联性。根据对业务的梳理,确定哪些表和主维表存在关联关系,并选择其中的某些表用于生成维度属性。以淘宝商品维度为例,根据对业务逻辑的梳理,可以得到商品与类目、SPU、卖家、店铺等维度存在关联关系。第四步:确定维度属性。本步骤主要包括两个阶段,其中第一个阶段是从主维表中选择维度属性或生成新的维度属性;第二个阶段是从相关维表中选择维度属性或生成新的维度属性。以淘宝商品维度为例,从主维表(s_auction_auctions)和类目、SPU、卖家、店铺等相关维表中选择维度属性或生成新的维度属性。

维度设计高级主题

维度整合

第一种是垂直整合,即不同的来源表包含相同的数据集,只是存储的信息不同。

比如淘宝会员在源系统中有多个表,如会员基础信息表、会员扩展信息表、淘宝会员等级信息表、天猫会员等级信息表,这些表都属于会员相关信息表,依据维度设计方法,尽量整合至会员维度模型中,丰富其维度属性。 第二种是水平整合,即不同的来源表包含不同的数据集,不同子集之间无交叉,也可以存在部分交叉。

比如针对蚂蚁金服的数据仓库,其采集的会员数据有淘宝会员、1688会员、国际站会员、支付宝会员等,是否需要将所有的会员整合到一个会员表中呢?如果进行整合,首先需要考虑各个会员体系是否有交叉,如果存在交叉,则需要去重;如果不存在交叉,则需要考虑不同子集的自然键是否存在冲突,如果不冲突,则可以考虑将各子集的自然键作为整合后的表的自然键;另一种方式是设置超自然键,将来源表各子集的自然键加工成一个字段作为超自然键。在阿里巴巴,通常采用将来源表各子集的自然键作为联合主键的方式,并且在物理实现时将来源字段作为分区字段。 水平拆分

维度通常可以按照类别或类型进行细分。

比如淘系商品表,根据业务线或行业等可以对商品进行细分,如淘宝的商品、天猫的商品、1688的商品、飞猪旅行的商品、淘宝海外的商品、天猫国际的商品等。不同分类的商品,其维度属性可能相同,也可能不同。比如航旅的商品和普通的淘系商品,都属于品,都有商品价格、标题、类型、上架时间、类目等维度属性,但是航旅的商品除了有这些公共属性外,还有酒店、景点、门票、旅行等自己独特的维度属性。 两种解决方案:

方案1:是将维度的不同分类实例化为不同的维度,同时在主维度中保存公共属性;方案2:是维护单一维度,包含所有可能的属性。 参考原则

扩展性:当源系统、业务逻辑变化时,能通过较少的成本快速扩展型,保持核心模型的相对稳定性。软件工程中的高内聚、低稠合的思想是重要的指导方针之一。效能:在性能和成本方面取得平衡。通过牺牲一定的存储成本,达到性能和逻辑的优化。易用性:模型可理解性高、访问复杂度低。用户能够方便地从模型中找到对应的数据表,并能够方便地查询和分析。 根据数据模型设计思想,在对维度进行水平拆分时,主要考虑如下两个依据。

第一个依据是维度的不同分类的属性差异情况。

当维度属性随类型变化较大时,将所有可能的属性建立在一个表中是不切合实际的,也没有必要这样做,此时建议采用方案。定义一个主维度用于存放公共属性;同时定义多个子维度,其中除了包含公共属性外,还包含各自的特殊属性。比如在阿里巴巴数据仓库维度体系中,依据此方法,构建了商品维度、航旅商品维度等。公共属性一般比较稳定,通过核心的商品维度,保证了核心维度的稳定性;通过扩展子维度的方式,保证了模型的扩展性。 第二个依据是业务的关联程度。

两个相关性较低的业务,稠合在一起弊大于利,对模型的稳定性和易用性影响较大。比如在阿里巴巴数据仓库维度体系中,对淘系商品和1688商品构建两个维度。虽然淘系和1688在底层技术实现上是统一的,但属于不同的BU,业务各自发展;在数据仓库层面,淘系和1688属于不同的数据集市,一般不会相互调用,业务分析人员一般只针对本数据集市进行统计分析。如果设计成一个维度,由于不同BU业务各自发展,1688业务变更,此维度需要变更,淘宝业务变更亦然,稳定性很差;在易用性方面,会给数据使用方造成困扰。 垂直拆分

维度是维度建模的基础和灵魂,维度属性的丰富程度直接决定了数据仓库的能力。在进行维度设计时,依据维度设计的原则,尽可能丰富维度属性,同时进行反规范化处理。对于具体实现时可能存在的问题:

一是在“水平拆分”中提到的,由于维度分类的不同而存在特殊的维度属性,可以通过水平拆分的方式解决此问题。二是某些维度属性的来源表产出时间较早,而某些维度属性的来源表产出时间较晚;或者某些维度属性的热度高、使用频繁,而某些维度属性的热度低、较少使用;或者某些维度属性经常变化,而某些维度属性比较稳定。在“水平拆分”中提到的模型设计的三个原则同样适合解决此问题。 出于扩展性、产出时间、易用性等方面的考虑,设计主从维度。主维表存放稳定、产出时间早、热度高的属性;从维表存放变化较快、产出时间晚、热度低的属性。

比如在阿里巴巴数据仓库中,设计了商品主维度和商品扩展维度。其中商品主维度在每日的1:30左右产出,而商品扩展维度由于有冗余的产出时间较晚的商品品牌和标签信息,在每日的3:00左右产出。另外,由于商品扩展维度有冗余的库存等变化较快的数据,对于主维度进行缓慢变化的处理较为重要。通过存储的冗余和计算成本的增加,实现了商品主模型的稳定和产出时间的提前,对于整个数据仓库的稳定和下游应用的产出都有较大意义。

事实表

事实表概念

事实表中的每行数据代表一个业务事件。“事实”表示的是业务事件的度量值(可以统计次数、个数、金额等)事实表作为数据仓库维度建模的核心,紧紧围绕着业务过程来设计,通过获取描述业务过程的度量来表达业务过程,包含了引用的维度和与业务过程有关的度量。事实表中一条记录所表达的业务细节程度被称为粒度。通常粒度可以通过两种方式来表述:

一种是维度属性组合所表示的细节程度:一种是所表示的具体业务含义。 作为度量业务过程的事实,一般为整型或浮点型的十进制数值,有可加性、半可加性和不可加性三种类型。

可加性事实是指可以按照与事实表关联的任意维度进行汇总。半可加性事实只能按照特定维度汇总,不能对所有维度汇总,比如库存可以按照地点和商品进行汇总,而按时间维度把一年中每个月的库存累加起来则毫无意义。不可加性,比如比率型事实。对于不可加性事实可分解为可加的组件来实现聚集。 相对维表来说,通常事实表要细长得多,行的增加速度也比维表快很多。维度属性也可以存储到事实表中,这种存储到事实表中的维度列被称为“退化维度”。与其他存储在维表中的维度一样,退化维度也可以用来进行事实表的过滤查询、实现聚合操作等。

事实表设计原则

原则 1:尽可能包含所有与业务过程相关的事实

分析哪些事实与业务过程相关,是设计过程中非常重要的关注点;在事实表中,尽量包含所有与业务过程相关的事实,即使存在冗余,由于事实通常是数字型,存储开销不会太大; 原则 2:只选择与业务过程相关的事实

如,订单的下单这个业务过程,事实表中不应该存在支付金额这个表示支付业务过程的事实; 原则 3:分解不可加性事实为可加的组件

如,订单的优惠率,应分解为订单原价金额与订单优惠金额两个事实存储在事实表中; 原则 4:在选择维度和事实之前必须先声明粒度

粒度用于确定事实表中一行所表示业务的细节层次,决定了维度模型的扩展性;每个维度和事实必须与所定义的粒度保持一致;设计事实表时,粒度定义越细越好,一般从最低级别的原子粒度开始;因为原子粒度提供了最大限度的灵活性,可以支持无法预期的各种细节层次的用户需求; 原则 5:在同一个事实表中不能有多种不同粒度的事实

疑问:怎么判断不同事实的粒度是否相同?粒度为票一级;(实际业务中,一个订单可以同时支付多张票)票支付金额和票折扣金额,两个事实的粒度为 “票级”,与定义的粒度一致;订单支付金额和订单票数,两个事实的粒度为 “订单级”,属于上一层订单级数据,与 “票级” 事实表的粒度不一致,且不能进行汇总;如果,以订单金额和订单票数这两个维度汇总总金额和总票数,会造成大量的重复计算; 原则 6:事实的单位要保持一致

如,订单金额、订单优惠金额、订单运费这 3 个事实,应该采用统一的计量单位,统一为元或者分,以方便使用; 原则 7:对事实的 null 值要处理

原因:在数据库中,null 值对常用数字型字段的 SQL 过滤条件都不生效;如,大于、小于、等于、大于或等于、小于或等于;处理:用 0 代替 null ; 原则 8:使用退化维度提高事实表的易用性

事实表中存储各种类型的常用维度信息,较少下游用户使用时关联多个表的操作;通过退化维度,可以实现对事实表的过滤查询、控制聚合层次、排序数据、定义主从关系等;易用性:对事实表,更较少关联操作、过滤查询、控制聚合层次、排序数据、定义主从关系等;

事实表设计方法

选择业务过程以及确定事实表类型

比如淘宝的订单流转的业务过程有四个:创建订单,买家付款,卖家发货,买家确认收货 明确了业务过程后,根据具体业务需求来选择与维度建模有关的业务过程。

比如买家付款这个业务过程,那么事实表应只包括买家付款这一个业务过程的单事务事实表总而言之就是选择了哪些业务过程,那么所建立的事实表应为包含了所有业务过程的累积快照事实表 声明粒度

粒度声明非常重要,尽量选择最细级别的原子粒度,以确保事实表的应用具有最大的灵活性比如一次购物车下单,一个父订单可能是购物车,一个子订单是每个商品的订单,那么订单事实表选择子订单粒度 确定维度

完成粒度声明意味着声明了主键,对应的维度组合就可以确定了应该选择能够清楚描述业务过程的维度信息例如订单事实表,粒度为子订单,相关的维度有卖家、买家、商品,收货人,时间等维度 确定事实

应该选择与业务过程有关的所有事实,且事实的粒度要和声明的粒度一致,比如在淘宝订单付款事务事实表中,同粒度的事实有子订单分摊的支付金额、邮费、优惠金额等 冗余维度

大数据的事实表设计中,冗余尽可能多的维度让下游方便使用,减少连表数量

事实表分类

事务型事实表

以每个事务或事件为单位,例如一个销售订单记录,一笔支付记录等,作为事实表里的一行数据。一旦事务被提交,事实表数据被插入,数据就不再进行更改,其更新方式为增量更新。单事务事实表:

单事务事实表,顾名思义,即针对每个业务过程设计一个事实表,这样设计的优点不言而喻,可以方便地对每个业务过程进行独立的分析研究。 多事务事实表:

多事务事实表,将不同的事实放到同一个事实表中,即同一个事实表包含不同的业务过程,多事务事实表在设计时有两种方法进行事实的处理: 例如:

以订单过程为例,一个订单业务过程可以简化为下单和支付两个业务事件,两个事件共享一个订单Id及相应商品的维度信息,但这两个事件可以有不同的业务度量,举例来讲就是下单时有下单金额,支付时有实际支付金额,优惠金额等等。对于数仓建设来讲,在描述订单业务过程,设计订单事实表模型时,就会面临一个选择:将下单和支付两个业务事件拆开,分别构建单事务事实表还是构建一张多事务事实表。

构建单事务事实表,优点在于各个事实表的业务语义明确,表分区字段直接采用表达的业务时间即可,方便下游使用方理解,缺点则是会冗余订单维度相关的数据,并且对于同时查询下单和支付度量时,会有表连接的计算开销。构建多事务事实表,此时表分区字段就不由具体的业务语义,需要在表中增加相应字段用明确时间语义。举例来讲对于2021-01-26的分区,需要有 ‘是否当天下单’&'是否当天支付’两个字段来辅助判断分区的时间语义,然后在表中包含下单和支付的度量,对于尚未发生的度量,可以置零。采用这种方案,对于下游使用有一定的理解难度,且度量中可能会有很多0值,但可以避免表连接问题。 周期型快照事实表

周期型快照事实表中不会保留所有数据,只保留固定时间间隔的数据,以具有规律性的、可预见的时间间隔记录事实。例如每天或每月的总销售金额,或每月的账户余额等。快照事实表的设计有些区别于事务事实表设计的性质。事务事实表的粒度能以多种方式表达,但快照事实表的粒度通常以维度形式声明;事务事实表是稀疏的,但快照事实表是稠密的;事务事实表中的事实是完全可加的,但快照模型将至少包含一个用来展示半可加性质的事实。快照采样状态

快照事实表以预定的间隔采样状态度量。这种间隔联合一个或多个维度,将被用来定义快照事实表的粒度,每行都将包含记录所涉及状态的事实。以淘宝交易卖家自然年汇总事实表为例进行介绍。淘宝活动运营小二或者卖家经常都需要看一些交易状态数据,比如自然年至今或者历史至今的下单金额、支付金额、支付买家数、支付商品件数等状态度量,对于卖家而言,可能每天早上都想看一下截至昨天的成交情况;对于小二而言,可能在频繁的活动周期就需要查看一次成交情况。这些状态度量可以每天通过事务事实表进行聚集,但随着时间跨度变大聚集效率会越来越低,因此需要设计快照事实表进行状态的度量,这里用于采样的周期间隔是每天。 快照粒度

事务事实表的粒度可以通过业务过程中所涉及的细节程度来描述,但快照事实表的粒度通常总是被多维声明,可以简单地理解为快照需要采样的周期以及什么将被采样。在淘宝交易卖家快照事实表中,粒度可以被理解为每天针对卖家的历史截至当日的下单支付金额进行快照。当然,快照周期不一定都按天来进行,也可以按照月或者季度来统计。比如淘宝交易有针对卖家加类目的每月汇总事实表,每月统计一次,同时维度也不仅一个,包含了卖家和类目。 密度与稀疏性

快照事实表和事务事实表的一个关键区别在密度上。事务事实表是稀疏的,只有当天发生的业务过程,事实表才会记录该业务过程的事实,如下单、支付等;而快照事实表是稠密的,无论当天是否有业务过程发生,都会记录一行,比如针对卖家的历史至今的下单和支付金额,无论当天卖家是否有下单支付事实,都会给该卖家记录一行。稠密性是快照事实表的重要特征,如果在每个快照周期内不记录行,比如和事务事实表一样,那么确定状态将变得非常困难。 半可加性

在快照事实表中收集到的状态度量都是半可加的。与事务事实表的可加性事实不同,半可加性事实不能根据时间维度获得有意义的汇总结果。比如对于淘宝交易事务事实表,可以对一个周期内的下单金额或者支付金额进行汇总,得到下单支付总额,但快照事实表在每个采样周期内是不能对状态度量进行汇总的。比如淘宝交易卖家快照事实表,无法对每天的历史至今的下单金额进行汇总,也没有汇总意义。虽然不能汇总,但可以计算一些平均值,比如计算每天一个下单的平均值。 累积型快照事实表

累积快照事实表用于跟踪业务事实的变化,覆盖过程的整个生命周期,通常具有多个日期字段来记录关键时间点。例如数据仓库中可能需要累积或者存储订单从下单开始,到订单商品被打包、运输、签收等各个业务阶段的时间点数据,来跟踪订单生命周期的进展情况。当这个业务过程进行时,事实表的记录也要不断更新。 事实表分类总结

事务事实表周期快照事实表累计快照事实表时间/日期离散时间事务点以有规律的、可预测的间隔产生快照用于时间跨度不确定的不断变化的工作流日期维度事务日期快照日期相关业务过程涉及的多个日期粒度每行代表实体的一个事务每行代表时间周期的一个实体每行代表代表一个实体的生命周期事实事务事实累积事实相关业务过程事实和时间间隔事实事实表加载插入插入插入与更新事实表更新不更新不更新业务过程变更时更新 事务事实表记录的事务层面的事实,用于跟踪业务过程的行为,并支持几种描述行为的事实,保存的是最原子的数据,也称为“原子事实表”。事务事实表中的数据在事务事件发生后产生,数据的粒度通常是每个事务一条记录。一旦事务被提交,事实表数据被插人,数据就不能更改,其更新方式为增量更新。 周期快照事实表以具有规律性的、可预见的时间间隔来记录事实,如余额、库存、层级、温度等,时间间隔为每天、每月、每年等,典型的例子如库存日快照表等。周期快照事实表的日期维度通常记录时间段的终止日,记录的事实是这个时间段内一些聚集事实值或状态度量。事实表的数据一旦插人就不能更改,其更新方式为增量更新。

,数据的粒度通常是每个事务一条记录。一旦事务被提交,事实表数据被插人,数据就不能更改,其更新方式为增量更新。

周期快照事实表以具有规律性的、可预见的时间间隔来记录事实,如余额、库存、层级、温度等,时间间隔为每天、每月、每年等,典型的例子如库存日快照表等。周期快照事实表的日期维度通常记录时间段的终止日,记录的事实是这个时间段内一些聚集事实值或状态度量。事实表的数据一旦插人就不能更改,其更新方式为增量更新。 累积快照事实表被用来跟踪实体的一系列业务过程的进展情况,它通常具有多个日期字段,用于研究业务过程中的里程碑过程的时间间隔。另外,它还会有一个用于指示最后更新日期的附加日期字段。由于事实表中许多日期在首次加载时是不知道的,而且这类事实表在数据加载完成后,可以对其数据进行更新,来补充业务状态变更时的日期信息和事实。

好文链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: