一、大数据领域建模综述
1.1 为什么需要数据建模
数据模型强调从业务、数据存取和使用角度合理存储数据。
数据模型方法,以便在性能、成本、效率之间取得最佳平衡
成本:良好的数据模型能极大地减少不必要的数据冗余,也能实现计算结果复用,极大地降低大数据系统中的存储和计算成本。
效率:良好的数据模型能极大地改善用户使用数据的体验,提高使用数据的效率。
质量:良好的数据模型能改善数据统计口径的不一致性,减少数据计算错误的可能性。
1.2 关系数据库系统和数据仓库
1.3 从 OLTP 和 OLAP 系统的区别看模型方法论的选择
1.4 典型的数据仓库建模方法论
1.4.1 ER 模型
采用 ER模型建设数据仓库模型的出发点是整合数据,将各个系统中的数据以整个企业角度按主题进行相似性组合和合并,并进行一致性处理,为数据分析决策服务,但是并不能直接用于分析决策。
ER 模型在实践中最典型的代表是 Teradata 公司基于金融业务发布 的 FS-LDM(Financial Services Logical Data Model),它通过对金融业务的高度抽象和总结,将金融业务划分为10大主题,并以设计面向金融仓库模型的核心为基础,企业基于此模型做适当调整和扩展就能快速落地实施。
1.4.2 维度模型
1.4.3 Data Vault 模型
1.4.4 Anchor 模型
1.5 阿里巴巴数据模型实践综述
第一个阶段:构建在 Oracle 上,数据完全以满足报表需求为目的
第二个阶段:引入了当时 MPP 架构体系的 Greenplum,ODL(操作数据层)+BDL(基础数据层)+IDL(接口数据层)+ADL (应用数据层);BDL希望引入 ER 模型,加强 数据的整合,构建一致的基础数据模型,但构建 ER 模型时遇到了比较大的困难和挑战,互联网业务的快速发展、人员的快速变化、业务知识功底的不够全面,导致 ER 模型设计迟迟不能产出。至此,我们也得到了一个经验:在不太成熟、快速变化的业务面前,构建 ER 模型的风险非常大,不太适合去构建 ER 模型。
第三个阶段:迎来了以Hadoop 为代表的分布式存储计算平台的快速发展,同时阿里巴 巴集团自主研发的分布式计算平台 MaxCompute 也在紧锣密鼓地进行着。以 Kimball 的维度建模为核心理念的模型方法论,构建了阿里巴巴集团的公共层模型数据架构体系。
二、阿里巴巴数据整合及管理体系
面对爆炸式增长的数据,如何建设高效的数据模型和体系,对这些 数据进行有序和有结构地分类组织和存储,避免重复建设和数据不一致性,保证数据的规范性,一直是大数据系统建设不断追求的方向。
2.1 概述
核心:从业务架构设计(如何快速上手工作)到模型设计,从数据研发到数据服务,做到数据可管理、可追溯、可规避重复建设。
2.1.1 定位及价值
建设统一的、规范化的数据接入层( ODS )和数据中间层( DWD 和 DWS ),通过数据服务和数据产品,完成服务于阿里巴巴的大数据系统建设,即数据公共层建设。
业务板块:根据业务属性划分板块,板块之间的指标或业务重叠性较小。
规范定义:一套数据规范命名体系,用在模型设计中
模型设计:以维度建模理论为基础,基于维度建模总线架构,构建一致性的维度和事实(进行规范定义)。
2.2 规范定义
规范定义指以维度建模作为理论基础,构建总线矩阵,划分和定义 数据域、业务过程、维度、度量/原子指标、修饰类型、修饰词、时间周期、派生指标。
2.2.1 名词术语
数据域(主题域)
业务过程
时间周期
修饰类型
修饰词
度量/原子指标
维度
维度属性
派生指标
2.2.2 指标体系
一、基本原则
组成体系之间的关系
原子指标、修饰类型及修饰词,直接归属在业务过程下,其中修饰词继承修饰类型的数据域
派生指标可以选择多个修饰词,修饰词之间的关系为"或"或者"且",由派生指标具体语义决定
派生指标唯一归属一个原子指标,继承原子指标的数据域,与修饰词的数据域无关
原子指标有确定的英文字段名、数据类型和算法说明;派生指标要继承原子指标的英文名、数据类型和算法要求
命名约定
命名所用术语。指标命名尽量使用英文简写,其次是英文。太长也可以考虑汉语拼音首字母
业务过程。英文名:用英文或英文的缩写或者中文拼音简写
原子指标。英文名:动作+度量
修饰词。只有时间周期才会有英文名
派生指标。英文名:原子指标英文名+时间周期修饰词(3位,例如_1d)+序号(4位,例如_001)
算法
二、操作细则
派生指标可以分为三类:事务型指标、存量型指标和复合型指标。
事务型指标:是指对业务活动进行衡量的指标。例如新发商品数、 重发商品数、新增注册会员数、订单支付金额,这类指标需维护 原子指标及修饰词,在此基础上创建派生指标。
存量型指标:是指对实体对象(如商品、会员)某些状态的统计。例如商品总数、注册会员总数,这类指标需维护原子指标及修饰词,在此基础上创建派生指标,对应的时间周期 一般为“历史截至当前某个时间”。
复合型指标:是在事务型指标和存量型指标的基础上复合而成的。例如浏览 UV-下单买家数转化率 , 有些需要 创 建新原子指标, 有些则可以在事务型或存量型原子指标的基础上增加修饰词得到派生指标。
2.3 模型设计
2.3.1 指导理论
数据模型的维度设计主要以维度建模理论为基础,基于维度数据模型总线架构,构建一致性的维度和事实。
2.3.2 模型层次
操作数据层(ODS):把操作系统数据几乎无处理地存放在数据仓库系统中。
公共维度模型层(CDM):存放明细事实数据、维表数据及公共指标汇总数据 ,其中明细事实数据、维表数据一般根据 ODS 层数据加工生成 ;公共指标汇总数据一般根据维表数据和明细事实数据加工生成。
CDM 层又细分为 DWD 层和 DWS 层,分别是明细数据层和汇总数据层,采用维度模型方法作为理论基础 ,更多地采用一些维度退化手法, 将维度退化至事实表中,减少事实表和维表的关联 ,提高明细数据表的易用性;同时在汇总数据层, 加强指标的维度退化, 采取更多的宽表化手段构建公共指标数据层,提升公共指标的复用性,减少重复加工。其主要功能如下。
组合相关和相似数据:采用明细宽表,复用关联计算,减少数据扫描。
公共指标统一加工:基于 OneData体系构建命名规范、口径一致 和算法统一 的统计指标,为上层数据产品、应用和服务提供公共指标建立逻辑汇总宽表。
建立一致性维度:建立一致的数据分析维表,降低数据计算口径、算法不统一的风险。
应用数据层(ADS):存放数据产品个性化的统计指标数据,根据 CDM 层与 ODS 层加工生成 。
阿里巴巴通过构建全域的公共层数据,极大地控制了数据规模的增长趋势
模型架构图
2.3.3 基本原则
一个逻辑或者物理模型由哪些记录和字段组成,应该遵循最基本的软件设计方法论的高内聚和低耦合原则。主要从数据业务特性和访问特性两个角度来考虑:将业务相近或者相关、粒度相同的数据设计为一个逻辑或者物理模型;将高概率同时访问的数据放一起,将低概率同时访问的数据分开存储。
建立核心模型与扩展模型体系,核心模型包括的字段支持常用的核心业务,扩展模型包括的字段支持个性化或少量应用的需要 ,不能让扩展模型的宇段过度侵入核心模型,以免破坏核心模型的架构简洁性与可维护性。
越是底层公用的处理逻辑越应该在数据调度依赖的底层进行封装与实现,不要让公用的处理逻辑暴露给应用层实现,不要让公共逻辑多处同时存在。
适当的数据冗余可换取查询和刷新性能,不宜过度冗余与数据复制。
处理逻辑不变,在不同时间多次运行数据结果确定不变。
具有相同含义的字段在不同表中的命名必须相同,必须使用规范定义中的名称。
表命名需清晰、一致,表名需易于消费者理解和使用。
2.4 模型实施
2.4.1 业界常用模型实施过程
构建维度模型一般要经历四个阶段:
第一个阶段是高层模型设计时期 ,定义业务过程维度模型的范围,提供每种星形模式的技术和功能描述;直接产出目标是创建高层维度模型图,它是对业务过程中的维表和事实表的图形描述。确定维表创建初始属性列表,为每个事实表创建提议度量;
第二个阶段是详细模型设计时期,对每个星形模型添加属性和度量信息;确定每个维表的属性和每个事实表的度量,并确定信息来源的位置、定义,确定属性和度量如何填入模型的初步业务规则。
第三个阶段是进行模型的审查、再设计和验证,本阶段主要召集相关人员进行模型的审查和验证,根据审查结果对详细维度进行再设计。
第四个阶段是产生详细设计文档,提交 ETL 设计和开发,最后,完成模型详细设计文档,提交 ETL 开发人员,进入 ETL 设计和开发阶段,由 ETL 人员完成物理模型的设计和开发。
2.4.2 OneData实施过程
指导方针
首先,在建设大数据数据仓库时,要进行充分的业务调研和需求分析。这是数据仓库建设的基石,业务调研和需求分析做得是否充分直接决定了数据仓库建设是否成功。
其次,进行数据总体架构设计,主要是根据数据域对数据进行划分;按照维度建模理论,构建总线矩阵、抽象出业务过程和维度。
再次,对报表需求进行抽象整理出相关指标体系, 使用 OneData 工具完成指标规范定义和模型设计。
最后,就是代码研发和运维。
实施工作流
(1)数据调研
业务调研:需要了解各个业务领域、业务线的业务有什么共同点和不同点 ,以及各个业务线可以细分为哪几个业务模块,每个业务模块具体的业务流程又是怎样的。业务调研是否充分,将会直接决定数据仓库 建设是否成功
需求调研:需求调研的途径有两种:一是根据与分析师、业务运营人员的沟通 (邮件、 IM )获知需求;二是对报表系统中现有的报表进行研究分析;
(2)架构设计
数据域划分
数据域是指面向业务分析,将业务过程或者维度进行抽象的集合。业务过程可以概括为 一 个个不可拆分的行为事件,如下单、支付、退款。数据域需要抽象提炼,并且长期维护和更新,但不轻易变动。
构建总线矩阵
在进行充分的业务调研和需求调研后,就要构建总线矩阵了。需要 做两件事情:明确每个数据域下有哪些业务过程;业务过程与哪些维度相关,并定义每个数据域下的业务过程和维度。
规范定义
规范定义主要定义指标体系,包括原子指标、修饰词、时间周期和 派生指标。
模型设计
模型设计主要包括维度及属性的规范定义,维表、明细事实表和汇 总事实表的模型设计。
总结
OneData 的实施过程是一个高度迭代和动态的过程, 一般采用螺旋式实施方法。在总体架构设计完成之后,开始根据数据域进行迭代式模型设计和评审。在架构设计、规范定义和模型设计等模型实施过程中, 都会引入评审机制,以确保模型实施过程的正确性。
三、维度设计
3.1 维度设计基础
3.1.1 维度的基本概念
维度建模中,将度量称为“事实”,将环境描述为“维度”,维度是用于分析事实所需要的多样环境。例如,在分析交易过程时,可以通过买家、卖家、商品和时间等维度描述交易发生的环境。
维度所包含的表示维度的列,称为维度属性。维度属性是查询约束条件、分组和报表标签生成的基本来源,是数据易用性的关键。
维度使用主键标识其唯一性,主键也是确保与之相连的任何事实表 之间存在引用完整性的基础。
3.1.2 维度的基本设计方法
选择维度或新建维度。须保证维度的唯一性。
确定主维表。一般是ODS表,直接与业务系统同步。
确定相关维表。确定哪些表和主维表存在关联关系,并选择其中的某些表用于生成维度属性。
确定维度属性。第一阶段从主维表中选择维度属性或生成新的维度属性;第二阶段是从相关维表中选择维度属性或生成新的维度属性。
确认维度属性的几点提示:
尽可能生成丰富的维度属性
尽可能多地给出包括一些富有意义的文字性描述
区分数值型属性和事实
尽量沉淀出通用的维度属性
3.1.3 一致性维度和交叉探查
共享维表。比如在阿里巴巴的数据仓库中,商品、卖家、买家、 类目等维度有且只有一个。所以基于这些公共维度进行的交叉探查不会存在任何问题。
一致性上卷。其中一个维度的维度属性是另一个维度的维度属性 的子集,且两个维度的公共维度属性结构和内容相同。比如在阿 里巴巴的商品体系中,有商品维度和类目维度,其中类目维度的 维度属性是商品维度的维度属性的子集,且有相同的维度属性和 维度属性值。这样基于类目维度进行不同业务过程的交叉探查也 不会存在任何问题。
交叉属性。两个维度具有部分相同的维度属性。比如在商品维度中具有类目属性,在卖家维度中具有主营类目属性,两个维度具有相同的类目属性,则可以在相同的类目属性上进行不同业务过程的交叉探查。
3.2 维度设计高级主题
3.2.1 维度整合
应用间差异:
集成类型(同维度整合):
表整合:
3.2.2 水平拆分
如何设计维度:
模型设计重点考虑的三个原则:
扩展性:当源系统、业务逻辑变化时,能通过较少的成本快速扩 展模型,保持核心模型的相对稳定性。软件工程中的高内聚、低藕合的思想是重要的指导方针之一。
效能:在性能和成本方面取得平衡。通过牺牲一定的存储成本, 达到性能和逻辑的优化。
易用性:模型可理解性高、访问复杂度低。用户能够方便地从模型中找到对应的数据表,并能够方便地查询和分析。
模型设计重点考虑的两个依据:
方案参考:
3.2.3 垂直拆分
3.2.4 历史归档
归档策略 1:同前台归档策略,在数据仓库中实现前台归档算法,定期对历史数据进行归档。但存在一些问题,一是前台归档策略复杂,实现成本较高;二是前台归档策略可能会经常变化,导致数据仓库归档算法也要随之变化,维护和沟通成本较高。此方式适用于前台归档策略 逻辑较为简单,且变更不频繁的情况。
归档策略 2 :同前台归档策略,但采用数据库变更日志的方式。对 于如此庞大的数据量,阿里巴巴采用的数据抽取策略一般是通过数据库 binlog 日志解析获取每日增量,通过增量merge 全量的方式获取最新的 全量数据。可以使用增量日志的删除标志,作为前台数据归档的标志。通过此标志对数据仓库的数据进行归档。此方式不需要关注前台归档策 略,简单易行。但对前台应用的要求是数据库的物理删除只有在归档时 才执行,应用中的删除只是逻辑删除。
归档策略 3 :数据仓库自定义归档策略。可以将归档算法用简单、直接的方式实现,但原则是尽量比前台应用晚归档、少归档。避免出现数据仓库中已经归档的数据再次更新的情况。
如果技术条件允许,能够解析数据库 binlog 日志,建议使用归档策略 2 ,规避前台归档算法。具体可以根据自身数据仓库的实际情况进行选择。
3.3 维度变化
3.3.1 缓慢变化维
在 Kimball 的理论中,有三种处理缓慢变化维的方式,可以根据业务需求来进行选择:
重写维度值。不保留历史数据, 始终取最新数据(假设业务需求方不关心历史数据,则可以采用方案1)
插入新的维度行。保留历史数据,维度值变化前的事实和过去的维度值关联,维度值变化后的事实和当前的维度值关联。
添加维度列。采用第二种处理方式不能将变化前后记录的事实归一为变化前的维度或者归一为变化后的维度(不同业务部门需要统计各自的业绩,则需 要保留历史数据)
3.3.2 快照维表
在 Kimball 的维度建模中,必须使用代理键(不具有业务含义的键,区别于自然键)作为每个维表的主键,用于处理缓慢变化维。
阿里不使用代理键的原因:数据量大、ETL复杂化;不直接使用拉链表的原因:解释成本高、随着时间的推移,分区数量会极度膨胀
阿里通过快照方式,每天保留一份全量快照数据,简单而有效,方便好理解,但造成存储浪费,因此配合极限存储。
3.3.3 极限存储
透明化
分月做历史拉链表
局限性:首先,其产出效率很低,大部分极限存储通常需要 t-2 ;其次,对于变化频率高的数据并不能达到节约成本的效果。
3.3.4 微型维度
微型维度的创建是通过将一部分不稳定的属性从主维度中移出,并 将它们放置到拥有自己代理键的新表中来实现的。这些属性相互之间没有直接关联,不存在自然键。通过为每个组合创建新行的一次性过程来加载数据。
比如淘宝用户维度,用户的注册日期、年龄、性别、身份信息等基本不会发生变化,但用户 VIP 等级、用户信用评价等级会随着用户的行为不断发生变化。
其中 VIP 等级共有 8 个值,即 -1 ~6 ;用户信用评价等级共有 18 个值。假设基于 VIP 等级和用户信用评价等级构建微型维度,则在此微型维度中共有 8 x 18 个组合,即 144 条记录,代理键可能是 1~ 144
阿里在实践中并未使用此技术:
3.4 特殊维度
3.4.1 递归层次
层次结构扁平化
扁平化仅包含固定数量的级别,对于非平衡层次结构,可以通过预留级别的方式来解决,但扩展性较差(图为阿里巴巴中文站的类目体系,粗体部分为回填内容)
层次桥接表
3.4.2 行为维度
理解为事实衍生的维度,按照加工方式划分:
另一个维度的过去行为,如买家最近一次访问淘宝的时间、买家最近一次发生淘宝交易的时间等。
快照事实行为维度,如买家从年初截至当前的淘宝交易金额、买 家信用分值、卖家信用分值等。
分组事实行为维度,将数值型事实转换为枚举值。如买家从年初截至当前的淘宝交易金额按照金额划分的等级、买家信用分值按 照分数划分得到的信用等级等。
复杂逻辑事实行为维度,通过复杂算法加工或多个事实综合加工得到。如前面提到的卖家主营类目,商品热度根据访问、收藏、 加入购物车、交易等情况综合计算得到。
对于行为维度,有两种处理方式,其中一种是将其冗余至现有的维表中,如将卖家信用等级冗余至卖家维表中另一种是加工成单独的行为维表,如卖家主营类目。具体采用哪种方式主要参考如下两个原则:
3.4.3 多值维度
多值维度的处理方式
3.4.4 多值属性
e.g. 商品和 SKU、属性、标签都是多对多的关系
多值属性的处理方式:
保持维度主键不变,将多值属性放在维度的一个属性字段中(通过 k-v 对的形式放在 property 字段中,数据示例如下:10281239:156426871; 137396765:29229; 137400766:3226633)
保持维度主键不变,但将多值属性放在维度的多个属性字段中(卖家主营类目,只取TOP 3)
维度主键发生变化,一个维度值存放多条记录,扩展性好,使用方便(比如商品 SKU 维表,对于每个商品,有多少 SKU ,就有多少记录,主键是商品的 ID 和 SKU 的 ID)
3.4.5 杂项维度
杂项维度是由操作型系统中的指示符或者标志宇段组合而成的,一般不在一致性维度之列。
将这些字段建立到一个维表中,在事实表中只需保存一个外键即可。多个字段的不同取值组成 一条记录,生成代理键,存入维表中,并将该代理键保存到相应的事实表字段下。建议不要直接使用所有的组合生成完整的杂项维表,在抽取遇到新的组合时生成相应的记录即可。
阿里:存在非枚举字段,如交易留言、交易属性、交易标签等;通过子订单维度实现,且作为逻辑模型,不进行物理化。
四、事实表设计
4.1 事实表基础
4.1.1 事实表特性
事实表作为数据仓库维度建模的核心,紧紧围绕着业务过程来设计,通过获取描述业务过程的度量来表达业务过程,包含了引用的维度和与业务过程有关的度量。
事实表中一条记录所表达的业务细节程度被称为粒度。通常粒度可以通过两种方式来表述:一种是维度属性组合所表示的细节程度:一种是所表示的具体业务含义。
作为度量业务过程的事实,一般为整型或浮点型的十进制数值,有可加性、半可加性和不可加性三种类型。
可加性事实是指可以按照与事实表关联的任意维度进行汇总。
半可加性事实只能按照特定维度汇总, 不能对所有维度汇总,比如库存可以按照地点和商品进行汇总,而按时间维度把一年中每个月的库存累加起来则毫无意义。
完全不具备可加性,比如比率型事实。对于不可加性事实可分解为可加的组件来实现聚集。
维度属性也可以存储到事实表中,这种存储到事实表中的维度列被称为“退化维度”。与其他存储在维表中的维度一样 ,退化维度也可以 用来进行事实表的过滤查询、实 现聚合操作等。
事实表有三种类型 : 事务事实表、周期快照事实表和累积快照事实表。
事务事实表用来描述业务过程,跟踪空间或时间上某点的度量事件,保存的是最原子的数据,也称为“原子事实表“。
周期快照事实表以具有规律性的、可预见的时间间隔记录事实 ,时间间隔如每天、每月、每年等。
累积快照事实表用来表述过程开始和结束之间的关键步骤事件,覆盖过程的整个生命周期,通常具有多个日期字段来记录关键时间点,当过程随着生命周期不断变化时,记录也会随着过程的变化而被修改。
4.1.2 事实表设计原则
原则 1:尽可能包含所有与业务过程相关的事实
原则 2:只选择与业务过程相关的事实
原则 3:分解不可加性事实为可加的组件
对于不具备可加性条件的事实,需要分解为可加的组件。比如订单的优惠率,应该分解为订单原价金额与订单优惠金额两个事实存储在事实表中。
原则 4:在选择维度和事实之前必须先声明粒度
原则 5:在同一个事实表中不能有多种不同粒度的事实
事实表中的所有事实需要与表定义的粒度保持一致,在同一个事实表中不能有多种不同粒度的事实。
原则 6:事实的单位要保持一致
对于同一个事实表中事实的单位,应该保持一致。比如原订单金额、 订单优惠金额、订单运费金额这三个事实,应该采用一致的计量单位, 统 一 为元或分,以方便使用。
原则 7:对事实的 null 值要处理
对于事实表中事实度量为 null 值的处理,因为在数据 库中 null 值 对常用数字型字段的 SQL 过滤条件都不生效,比如大于、小于、等于、 大于或等于、小于或等于,建议用零值填充。
原则 8:使用退化维度提高事实表的易用性
4.1.3 事实表设计方法
对于维度模型设计采用四步设计方法:选择业务过程、声明粒度、确定维度、确定事实。
选择业务过程及确定事实表类型
在明确了业务需求以后,接下来需要进行详细的需求分析,对业务 的整个生命周期进行分析,明确关键的业务步骤,从而选择与需求有关的业务过程。
业务过程通常使用行为动词表示业务执行的活动。比如图 4.1中的淘宝订单流转的业务过程有四个:创建订单、买家付款、卖家发货、买家确认收货。在明确了流程所包含的业务过程后,需要根据具体的业务需求来选择与维度建模有关的业务过程。比如是选择买家付款这个业务过程,还是选择创建订单和买家付款这两个业务过程,具体根据业务情 况来确定。
在选择了业务过程以后,相应的事实表类型也随之确定了。比如选择买家付款这个业务过程,那么事实表应为只包含买家付款这一个业务过程的单事务事实表;如果选择的是所有四个业务过程,并且需要分析各个业务过程之间的时间间隔,那么所建立的事实表应为包含了所有四个业务过程的累积快照事实表。
声明粒度
粒度的声明是事实表建模非常重要的一步,意味着精确定义事实表 的每一行所表示的业务含义,粒度传递的是与事实表度量有关的细节层次。明确的粒度能确保对事实表中行的意思的理解不会产生混淆,保证所有的事实按照同样的细节层次记录。
应该尽量选择最细级别的原子粒度,以确保事实表的应用具有最大的灵活性。同时对于订单过程而言,粒度可以被定义为最细的订单级别。比如在淘宝订单中有父子订单的概念,即一个子订单对应一种商品,如 果拍下了多种商品,则每种商品对应一个子订单:这些子订单一同结算 的话,则会生成一个父订单。那么在这个例子中,事实表的粒度应该选择为子订单级别。
确定维度
完成粒度声明以后,也就意味着确定了主键,对应的维度组合以及相关的维度字段就可以确定了,应该选择能够描述清楚业务过程所处的环境的维度信息。比如在淘宝订单付款事务事实表中,粒度为子订单,相关的维度有买家、卖家、商品、收货人信息 、业务类型、订单时间等维度。
确定事实
事实可以通过回答“过程的度量是什么”来确定。应该选择与业务 过程有关的所有事实,且事实的粒度要与所声明的事实表的粒度一致。事实有可加性、半可加性、非可加性三种类型 , 需要将不可加性事实分解为可加的组件。
比如在淘宝订单付款事务事实表中,同粒度的事实有子订单分摊的支付金额、邮费、优惠金额等。
冗余维度
在传统的维度建模的星形模型中,对维度的处理是需要单独存放在专门的维表中的,通过事实表的外键获取维度。这样做的目的是为了减少事实表的维度冗余,从而减少存储消耗。而在大数据的事实表模型设计中,考虑更多的是提高下游用户的使用效率,降低数据获取的复杂性,减少关联的表数量。所以通常事实表中会冗余方便下游用户使用的常用维度,以实现对事实表的过滤查询、控制聚合层次、排序数据以及定义主从关系等操作。
比如在淘宝订单付款事务事实表中,通常会冗余大量的常用维度字段,以及商品类目、卖家店铺等维度信息。
4.2 事务事实表
订单作为交易行为的核心载体,直观反映了交易的状况。订单的流转会产生很多业务过程,而下单、支付和成功完结三个业务过程是整个 订单的关键节点。获取这三个业务过程的笔数、金额以及转化率是日常 数据统计分析的重点,事务事实表设计可以很好地满足这个需求。本节 将介绍三种不同事务事实表的设计方式,以及在淘宝交易订单中关于邮 费和折扣分摊到子订单的算法。
4.2.1 设计过程
任何类型的事件都可以被理解为一种事务。比如交易过程中的创建 订单、买家付款,物流过程中的揽货、发货、签收,退款中的申请退 款、 申请小二介入等,都可以被理解为一种事务。事务事实表, 即针对这些过程构建的一类事实表,用以跟踪定义业务过程的个体行为,提供丰富的分析能力,作为数据仓库原子的明细数据。下面以淘宝交易事务事实表为例,阐述事务事实表的一般设计过程。
选择业务过程
图 4.1 给出了淘宝交易订单的流转过程,其中介绍了四个重要过程:创建订单、买家付款、 卖家发货、买家 确认收货,即下单、支付 、 发货和成功完结四个业务过程。这四个业务过程不仅是交易过程中的重要时间节点 ,而且也是下游统计分析的重点,因此淘宝交易事务事实表 设计着重从这四个业务过程进行展开 。
Kimball 维度建模理论认为,为了便于进行独立的分析研究,应该为每个业务过程建立一个事实表。对于是否将不同业务过程放到同一个事实表 中,将在下一节中详细介绍。
确定粒度
业务过程选定以后,就要针对每个业务过程确定一个粒度,即确定事务事实表每一行所表达的细节层次。下面先介绍淘宝订单的产生过程。
对于每一种商品产生的订单就称为子订单,子订单记录了父订单的订单号,并且有子订单标志。如果在同一个店铺只购买了一种商品,则会将父子订单进行合并,只保留一条订单记录。如图 4.2 和图 4.3 所示示例。
卖家发货这个业务过程可以选择子订单粒度,即将每个子订 单作为卖家发货事实表的一个细节。然而,在实际操作中发现,卖家发货更多的是物流单粒度而非子订单粒度,同 一个子订单可以拆开成多个物流单进行发货。在事务事实表设 计过程中,秉承确定为最细粒度的原则,因此对于卖家发货确定为物流单粒度,和其他三个业务过程不同,这样可以更好地给下游统计分析带来灵活性。
确定维度
选定好业务过程并且确定粒度后,就可以确定维度信息了。在淘宝交易事务事实表设计过程中,按照经常用于统计分析的场景,确定维度包含: 买家、卖家、商品、商品类目、发货地区、收货地区、父订单维度以及杂 项维度。由于订单的属性较多,比如订单的业务类型、是否无线交易、订单的 attributes 属性等,对于这些使用较多却又无法归属到上述买卖家或商品维度中的属性,则新建一个杂项维度进行存放,如图 4.4所示。
确定事实
作为过程度量的核心,事实表应该包含与其描述过程有关的所有事实。以淘宝交易事务事实表为例,选定三个业务过程一一下单、支付和 成功完结,不同的业务过程拥有不同的事实。比如在下单业务过程中, 需要包含下单金额、下单数量、下单分摊金额;在支付业务过程中,包含支付金额、分摊邮费、折扣金额、红包金额、积分金额;在完结业务过程中包含确认收货金额等。由于粒度是子订单,所以对于一些父订单上的金额需要分摊到子订单上,比如父订单邮费、父订单折扣等。
5.冗余维度
在确定维度时,包含了买卖家维度、商品维度、类目维度 、收发货维度等, Kimball维度建模理论建议在事实表中只保存这些维表的外键, 而淘宝交易事务事实表在 Kimball 维度建模基础之上做了进 一 步的优 化,将买卖家星级、标签、店铺名称、商品类型、商品特征、商品属性、 类目层级等维度属性都冗余到事实表中,提高对事实表进行过滤查询、统计聚合的效率,如图 4.5 所示 。
4.2.2 单事务事实表
单事务事实表,顾名思义,即针对每个业务过程设计一个事实表。这样设计的优点不言而喻,可以方便地对每个业务过程进行独立的分析研究。1688 交易流程则采用这 种模式构建事务事实表。
1688 交易和淘宝交易相 似,主要流程也是下单、支付、发货和完结,而在这四个关键流程中 1688 交易选择下单和支付两个业务过程设 计事务事实表,分别是1688交易订单下单事务事实表和1688交易订单支付事务事实表。
选定业务过程后,将对每个业务过程确定粒度、维度和事实。对于 1688 交易订单下单事务事实表,确定子订单粒度,选择买家、卖家、商品、父订单、收货地区维度,事实包含下单分摊金额和折扣金额,如 图4.6 所示;而对于 1688 交易订单支付事务事实表 ,粒度和维度与交易订单下单事务事实表相同,所表达的事实则不 一样 ,包含支付金额、支付调整金额和支付优惠等,如图4.7 所示;
1688 交易针对下单和支付分别建立单事务事实表后,每天的下单记录则进入当天的下单事务事实表中,每天的支付记录进入当天的支付事务事实表中,由于事实表具有稀疏性质 ,因此只有当天数据才会进入当天的事实表中。下面以具体交易订单为例 ,展示单事务事实表的设计实例。
4.2.3 多事务事实表
多事务事实表,将不同的事实放到同一个事实表中,即同一个事实表包含不同的业务过程。多事务事实表在设计时有两种方法进行事实的处理:
如何选择:
当不同业务过程的度量比较相似、差异不大时,可以采用第 二种 多事务事实表的设计方式,使用同 一个字段来表示度量数据 。但 这种方式存在一个问题一一在同一个周期内会存在多条记录(如淘宝收藏商品事务事实表,增加【收藏删除类型】,collect/delete)
当不同业务过程的度量差异较大时,可以选择第一种多事务事实 表的设计方式,将不同业务过程的度量使用不同 字段冗余到 表 中,非当前业务过程则置零表示。这种方式所存在的问题是度量字段零值较多(如淘宝交易事务事实表,针对不同业务过程如下单,则打一个是否当天下单的标签)
4.2.4 两种事实表对比
业务过程
对于单事务事实表,一个业务过程建立一个事实表,只反映一个业务过程的事实 ;对于多事务事实表,在同 一个事实表 中反映多个业务过程。多个业务过程是否放到同一 个事实表中,首先需要分析不同业务过 程之间的相 似性和业务源系统。比如淘宝交易的下单、支付和成功完结 这三个业务过程是存在相似性的,都属于订单处理中的 一环,并且都来自于交易系统 ,因此适合放到同 一个事务事实表中。
粒度和维度
在考虑是采用单事务事实表还是多事务事实表时,另一个关键点就是粒度和维度,在确定好业务过程后,需要基于不同的业务过程确定粒度和维度,当不同业务过程的粒度相同,同时拥有相似的维度时,此时就可以考虑采用多事务事实表。如果粒度不同,则必定是不同的事实表。比如交易中支付和发货有不同的粒度,则无法将发货业务过程放到淘宝交易事务事实表中。
事实
对于不同的业务过程,事实往往是不同的,单事务事实表在处理事实上比较方便和灵活,仅仅体现同一个业务过程的事实即可, 而多事务事实表由于有多个业务过程, 所以有更多的事实需要处理。如果单一业务过程的事实较多,同时不同业务过程的事实又不相同,则可以考虑使 用单事务事实表,处理更加清晰 ; 若使用多事务事实表, 则会导致事实表零值或空值字段较多。
下游业务使用
单事务事实表对于下游用户而言更容易理解 , 关注哪个业务过程就使用相应的事务事实表;而多事务事实表包含多个业务过程,用户使用时往往较为困惑。1688 和淘宝交易分别采用了这两种方式,从日常使用来看,对于淘宝交易事务事实表下游用户确实有 一定的学习成本 。
计算存储成本
针对多个业务过程设计事务事实表,是采用单事务事实表还是多事务事实表,对于数据仓库的计算存储成本也是参考点之 一 ,当业务过程 数据来源于同 一个业务系统,具有相同的粒度和维度,且维度较多而事实相对不多时,此时可以考虑使用多事务事实表,不仅其加工计算成本 较低,同时在存储上也相对节省,是一种较优的处理方式。
4.2.5 父子事实的处理方式
4.2.6 事实的设计准则
事实完整性:尽可能多地获取所有的度量
事实一致性:事实表中统一计算可以保证度量的一致性(比如金额由数量*单价先在事实表算出来)
事实可加性:事务事实表中关注 更多的是可加性事实,下游用户在聚合统计时更加方便
4.3 周期快照事实表
4.3.1 特性
用快照采样状态
快照粒度
密度与稀疏性
半可加性
4.3.2 实例
4.3.3 注意事项
事务与快照成对设计
附加事实
周期到日期度量
4.4 累积快照事实表
4.4.1 设计过程
4.4.2 特点
数据不断更新
多业务过程日期
4.4.3 特殊处理
非线性过程
多源过程
业务过程取舍
4.4.4 物理实现
全量表的形式:此全量表一般为日期分区表,每天的 分区存储昨天的全量数据和当天的增量数据合并的结果,保证每条记录 的状态最新。此种方式适用于全量数据较少的情况。
全量表的变化形式:比如针对交易订单,我们以 200 天作为订单从产生到消亡的最大间隔。设计最近 200 天的交易订单累积快照事实表,每天的分 区存储最近 200 天的交易订单而 200 天之前的订单则按照 gmt_create 创 建分区存储在归档表中。
业务实体的结束时间分区:每天的分区存放当天结 束的数据,设计一个时间非常大的分区,比如 3000-12-31 ,存放截至当前未结束的数据。由于每天将当天结束的数据归档至当天分区中,时间 非常大的分区数据量不会很大, ETL 性能较好;并且无存储的浪费,对于业务实体的某具体实例,在该表的全量数据中唯一。但接口等原因,存在结束标志的确认问题,有以下两个方案:
4.5 三种事实表的比较
4.6 无事实的事实表
4.7 聚集型事实表DWS
4.7.1 聚集的基本原则
一致性。表必须提供与查询明细粒度数据一致的查询结果。
避免单一表设计。不要在同一个表中存储不同层次的聚集数据;否则将会导致双重计算或出现更糟糕的事情。在聚集表中有些行 存放按天汇总的交易额,有些行存放按月汇总的交易额,这将会让使用者产生误用导致重复计算。行之有效的另一种方法是把按天与按月汇总的交易额用两列存放,但是需要在列名或者列注释上能分辨出来。
聚集粒度可不同。聚集并不需要保持与原始明细粒度数据一样的粒度,聚集只关心所需要查询的维度。
4.7.2 聚集的基本步骤
确定聚集维度
在原始明细模型中会存在多个描述事实的维度,如日期、商品类别、 卖家等,这时候需要确定根据什么维度聚集,如果只关心商品的交易额 情况,那么就可以根据商品维度聚集数据。
确定一致性上钻
确定聚集事实
4.7.3 阿里公共汇总层
基本原则
交易汇总表设计
最近1天商品粒度汇总表
最近N天卖家粒度汇总表
最近1天卖家、买家、商品粒度汇总表
最近1天二级类目汇总表
4.7.4 聚集补充说明
CIO之家 www.ciozj.com 公众号:imciow