2.3 Data Vault模型
Data Vault是一种数据仓库建模方法,用来存储来自多个操作型系统的完整的历史数据。Data Vault方法需要跟踪所有数据的来源,因此其中每个数据行都要包含数据来源和装载时间属性,用以审计和跟踪数据值所对应的源系统。Data Vault不区分数据在业务层面的正确与错误,它保留操作型系统的所有时间的所有数据,装载数据时不做数据验证、清洗等工作,这点明显有别于其他数据仓库建模方法。Data Vault建模方法显式地将结构信息和属性信息分离,能够还原业务环境的变化。Data Vault允许并行数据装载,不需要重新设计就可以实现扩展。
2.3.1 Data Vault模型简介
Data Vault(DV)模型用于企业级的数据仓库建模,是Dan Linstedt在20世纪90年代提出的。在最近几年,Data Vault模型获得了很多关注。
Dan Linstedt将Data Vault模型定义如下:
Data Vault是面向细节的,可追踪历史的,一组有连接关系的规范化的表的集合。这些表可以支持一个或多个业务功能。它是一种综合了第三范式(3NF)和星型模型优点的建模方法。其设计理念是要满足企业对灵活性、可扩展性、一致性和对需求的适应性要求,是一种专为企业级数据仓库量身定制的建模方式。
从上面的定义可以看出,Data Vault既是一种数据建模的方法论,又是构建企业数据仓库的一种具体方法。Data Vault建模方法论里不仅定义了Data Vault的组成部分和组成部分之间的交互方式,还包括了最佳实践来指导构建企业数据仓库。例如,业务规则应该在数据的下游实现,就是说Data Vault只按照业务数据的原样保存数据,不做任何解释、过滤、清洗、转换。即使从不同数据源来的数据是自相矛盾的(例如同一个客户有不同的地址), Data Vault模型不会遵照任何业务的规则,如“以系统A的地址为准”。Data Vault模型会保存两个不同版本的数据,对数据的解释将推迟到整个架构的后一个阶段(数据集市)。
2.3.2 Data Vault模型的组成部分
Data Vault模型有中心表(Hub)、链接表(Link)、附属表(Satellite)三个主要组成部分。中心表记录业务主键,链接表记录业务关系,附属表记录业务描述。
1.中心表
中心表用来保存一个组织内的每个实体的业务主键,业务主键唯一标识某个业务实体。中心表和源系统表是相互独立的。当一个业务主键被用在多个系统时,它在Data Vault中也只保留一份,其他的组件都链接到这一个业务主键上。这就意味着业务数据都集成到了一起。表2-13列出了中心表应该包含的所有的列。
表2-13 中心表的属性
2.链接表
链接表是中心表之间的链接。一个链接表意味着两个或多个中心表之间有关联。一个链接表通常是一个外键,它代表着一种业务关系。表2-14列出了链接表的所有字段。
表2-14 链接表的属性
在Data Vault里,每个关系都以多对多方式关联,这给模型带来了很大的灵活性。无论数据在源系统中是什么关系,都可以保存在Data Vault模型中。
3.附属表
附属表用来保存中心表和链接表的属性,包括所有的历史变化数据。一个附属表总有一个且唯一一个外键引用到中心表或链接表。表2-15列出了附属表的所有字段。
表2-15 附属表的属性
在Data Vault模型的标准定义里,附属表的主键应该是附属表里参照到中心表或链接表的外键字段和装载时间字段的组合。尽管这个定义是正确的,但从技术角度考虑,我们最好还是增加一个代理键。使用只有一列的代理键更易维护。另外,对外键列和装载时间列联合建立唯一索引,也是一个好习惯。
2.3.3 Data Vault模型的特点
一个设计良好的Data Vault模型应该具有以下特点:
● 所有数据都基于时间来存储,即使数据是低质量的,也不能在ETL过程中处理掉。
● 依赖越少越好。
● 和源系统越独立越好。
● 设计上适合变化。
◆ 源系统中数据的变化。
◆ 在不改变模型的情况下可扩展。
● ETL作业可以重复执行。
● 数据完全可追踪。
2.3.4 Data Vault模型的构建
在Data Vault模型中,各个实体有着严格、通用的定义与准确、灵活的功能描述,这不但使得Data Vault模型能够最直观、最一般地反映数据之间内含的业务规则,同时也为构建Data Vault模型提供了一致而普遍的方法。
Data Vault模型的建立可以遵循如下步骤:
1.设计中心表
首先要确定企业数据仓库要涵盖的业务范围;其次要将业务范围划分为若干原子业务实体,比如客户、产品等;然后,从各个业务实体中抽象出能够唯一标识该实体的业务主键,该业务主键要在整个业务的生命周期内不会发生变化;最后,由该业务主键生成中心表。
2.设计链接表
链接表体现了中心表之间的业务关联。设计链接表,首先要熟悉各个中心表代表的业务实体之间的业务关系,可能是两个或者多个中心表之间的关系。根据业务需求,这种关系可以是1对1、1对多,或者多对多的。
然后,从相互之间有业务关系的中心表中,提取出代表各自业务实体的中心表主键,这些主键将被加入到链接表中,组合构成该链接表的主键。同样出于技术的原因,需要增加代理键。
在生成链接表的同时,要注意如果中心表之间有业务交易数据的话,就需要在链接表中保存交易数据,有两种方法,一是采用加权链接表,二是给链接表加上附属表来处理交易数据。
3.设计附属表
附属表包含了各个业务实体与业务关联的详细的上下文描述信息。设计附属表,首先要收集各个业务实体在提取业务主键后的其他信息,比如客户住址、产品价格等;由于同一业务实体的各个描述信息不具有稳定性,会经常发生变化,所以,在必要的时候,需要将变化频率不同的信息分隔开来,为一个中心表建立几个附属表,然后提取出该中心表的主键,作为描述该中心表的附属表的主键。
当业务实体之间存在交易数据的时候,需要为没有加权的链接表设计附属表,也可以根据交易数据的不同变化情况设计多个附属表。
4.设计必要的PIT表
Point—In—Time表是由附属表派生而来的。如果一个中心表或者链接表设计有多个附属表的话,而为了访问数据方便,就有用到PIT表的可能。
PIT表的主键也是由其所归属的中心表提取而来,该中心表有几个附属表,PIT表就至少应该有几个字段来存放各个附属表的变化对比时间。
建立Data Vault模型时应该参照如下的原则:
(1)关于中心表的原则
● 中心表的主键不能够直接“伸入”到其他中心表里面。就是说,不存在父子关系的中心表。各个中心表之间的关系是平等的,这也正是Data Vault模型灵活性与扩展性之所在。
● 中心表之间必须通过链接表相关联,通过链接表可以连接两个以上的中心表。
● 必须至少有两个中心表才能产生一个有意义的链接表。
● 中心表的主键总是“伸出去”的(到链接表或者附属表)。
(2)关于链接表的原则
● 链接表可以跟其他链接表相连。
● 中心表和链接表都可以使用代理键。
● 业务主键从来不会改变,就是说中心表的主键也即链接表的外键不会改变。
(3)关于附属表的原则
● 附属表必须是连接到中心表或者链接表上才会有确定的含义。
● 附属表总是包含装载时间和失效时间,从而包含历史数据,并且没有重复的数据。
● 由于数据信息的类型或者变化频率快慢的差别,描述信息的数据可能会被分隔到多个附属表中去。
2.3.5 Data Vault模型实例
下面用一个销售订单的例子说明如何将关系模型转换为Data Vault模型,以及如何向转换后的Data Vault模型装载数据。关系模型如图2-5所示,共有省、市、客户、产品类型、产品、订单、订单明细7个表。
图2-5 销售订单关系模型
1.将关系模型转换为Data Vault模型
首先按照下面的步骤转换中心表。
(1)确定中心实体。示例中的客户、产品类型、产品、订单、订单明细这5个实体是订单销售业务的中心实体。省、市等地理信息表是参考数据,不能算是中心实体,实际上是附属表。
(2)把第一步确定的中心实体中有入边的实体转换为中心表,因为这些实体被别的实体引用。把客户、产品类型、产品、订单转换成中心表。
(3)把第一步确定的中心实体中没有入边且只有一条出边的实体转换为中心表。该示例中没有这样的表。
如表2-16所示列出了所有中心表。
表2-16 销售订单中心表
每个中心表只有代理键、业务主键、装载时间、数据来源四个字段。在这个示例中,业务主键就是关系模型中表的主键字段。
然后按照下面的步骤转换链接表。
(1)把示例中没有入边且有两条或两条以上出边的实体直接转换成链接表。符合条件的是订单明细表。
(2)把示例中除第一步以外的外键关系转换成链接表。订单和客户之间建立链接表,产品和产品类型之间建立链接表。注意Data Vault模型中的每个关系都是多对多关系。
如表2-17所示列出了所有链接表。
表2-17 销售订单链接表
链接表中包含有代理键、关联的中心表的一个或多个主键、装载时间、数据来源等字段。
最后转换附属表。附属表为中心表和链接表补充属性。所有源库中用到的表的非键属性都要放到Data Vault模型的附属表中。
如表2-18所示列出了所有附属表。
表2-18 销售订单附属表
附属表中包含有代理键、关联的中心表或链接表的主键、装载时间、失效时间、数据来源、关联的中心表或链接表所对应的关系模型表中的一个或多个非主键属性等字段。
转换后的Data Vault模型如图2-6所示。
图2-6 销售订单Data Vault模型
2.向Data Vault模型的表中装载数据
现在Data Vault模型的中心表、链接表、附属表都已经建立好,需要向其中装载数据,数据的来源是关系模型中的表。假设Data Vault的表使用MySQL数据库建立,代理键使用自增列,装载时间使用时间戳数据类型,在插入数据时,这两列不用显式赋值,数据会自动维护。数据来源字段简单处理,就填写与之相关的表名。附属表的失效时间字段,初始值填写一个很大的默认时间,这里插入‘2200-01-01'。
使用以下的SQL代码装载hub_product中心表、link_order_product链接表、sat_order_product附属表,其他表的装载语句类似,这里从略。
-- 装载hub_product中心表 insert intohub_product (product_id, record_source) selectproduct_id, 'product' fromproduct; -- 装载link_order_product链接表 insert intolink_order_product( hub_sales_order_id, hub_product_id, record_source) selecthub_sales_order_id, hub_product_id, 'hub_sales_order, hub_product, sales_order_item' fromhub_sales_order t1, hub_product t2, sales_order_item t3 wheret1.sales_order_id = t3.sales_order_id andt2.product_id = t3.product_id; -- 装载sat_order_product附属表 insert intosat_order_product ( link_order_product_id, load_end_dts, record_source, unit_price, quantity) selectlink_order_product_id, '2200-01-01', 'link_order_product, hub_sales_order, hub_product, sales_order_item', t4.unit_price, t4.quantity fromlink_order_product t1, hub_sales_order t2, hub_product t3, sales_order_item t4 wheret1.hub_sales_order_id = t2.hub_sales_order_id andt1.hub_product_id = t3.hub_product_id andt4.sales_order_id = t2.sales_order_id andt4.product_id = t3.product_id;