10.2.1 维度整合
我们先来看数据仓库的定义:
数据仓库是一个面向主题的、集成的、 非易失的且随时间变化的数据集合,
用来支持管理人员的决策。
其中集成是数据仓库的四个特性中最重要的一个。
数据仓库的重要数据来源是大量的、分散的面向应用的操作型环境。
不同的应用在设计过程中,可以自由决策 ,主要满足本应用的需求,
很少会考虑和其他系统进行数据集成。
应用之间的差异具体表现在如下几个方面:
1、应用在编码、命名习惯、度量单位等方面会存在很大的差异。
比如不同应用对于用户的性别编码不同,有0和1、F和M等;
不同应用的用户 ID 含义相同,但字段名称不同,有 user,user_id等;
不同应用对于金额的度量单位不同,有元、分等。
2、应用出于性能和扩展性的考虑,或者随技术架构的演变,
以及业务的发展,采用不同的物理实现。
拆分至不同类型数据库中,
部分数据采用关系型数据库存储(如 Oracle MySQL 等),
部分数据采用 NoSQL 数据库存储(如 HBase Tair 等)。
拆分成同型数据库中的多个物理表,
比如对于淘宝商品,
有商品主表和商品扩展表,
商品主表存储商品基本信息,
商品扩展表存储商品特殊信息,
如不同产品线的定制化信息等;
对于淘宝会员,
有会员主表和会员扩展表,
会员主表存储用户基本信息,
会员扩展表存储用户扩展信息,如用户的各种标签信息等。
所以数据由面向应用的操作型环境进人数据仓库后,需要进行数据集成。
将面向应用的数据转换为面向主题的数据仓库数据,本身就是一种集成。
【集成的体现方面】
1、命名规范的统一。
2、字段类型的统一。
3、公共代码及代码值的统一。
4、业务含义相同的表的统一。
主要依据高内聚、低稠合的理念,
在物理实现中,将业务关系大、源系统影响差异小的表进行整合;
将业务关系小、游、系统影响差异大 的表进行分而置之。
【集成的方式】
1、采用主从表的设计方式,
将两个表或多个表都有的字段放在主表中(主要基本信息),
从属信息分别放在各自的从表中。
对于主表中的主键,
要么采用复合主键、源主键和系统或表区别标志:
要么采用唯一主键、“源主键和系统或表区别标志”生成新的主键。
通常建议采用复合主键的方式。
2、直接合并,
共有信息和个性信息都放在同一个表中。
如果表字段的重合度较低,则会出现大量空值,
对于存储和易用性会有影响,需谨慎选择。
3、不合并,
因为源表的表结构及主键等差异很大,无法合并,
使用数据仓库里的多个表存放各自的数据。
维表的整合涉及的内容和上面介绍的几个方面相同,
下面重点看表级别的整合,有两种表现形式。
【整合的表现形式】
第一种是垂直整合,
即不同的来源表包含相同的数据集,
只是存储的信息不同。
比如淘宝会员在源系统中有多个表,
如会员基础信息表、会员扩展信息表、
淘宝会员等级信息表、天猫会员等级信息表,
这些表都属于会员相关信息表,依据维度设计方法,
尽量整合至会员维度模型中,丰富其维度属性。
user | d1 | d2 | d3 | d4 | d5 | d6 | …… |
---|---|---|---|---|---|---|---|
第二种是水平整合,
即不同的来源表包含不同的数据集,
不同子集之间无交叉,
也可以存在部分交叉。
比如针对蚂蚁金服的数据仓库,
其采集的会员数据有淘宝会员、 1688 会员、国际站会员、支付宝会员等,
是否需要将所有的会员整合到一个会员表中呢?
如果进行整合,首先需要考虑各个会员体系是否有交叉,
如果存在交叉,则需要去重;
如果不存在交叉,则需要考虑不同子集的自然键是否存在冲突,
如果不冲突, 则可以考虑将各子集的自然键作为整合后的表的自然键;
另一种方式是设置超自然键,
将来源表各子集的自然键加工成一个字段作为超自然键。
在阿里巴巴,通常采用将来源表各子集的自然键作为联合主键的方式,
并且在物理实现时将来源字段作为分区字段。
user | source | |
---|---|---|
s1 | ||
s2 | ||
s3 | ||
s4 | ||
s5 | ||
s6 | ||
…… |
有整合就有拆分,到底是整合还是拆分,由多种因素决定。
下面两节讨论维度的水平拆分和垂直拆分。
10.2.2 水平拆分
维度通常可以按照类别或类型进行细分。
比如淘系商品表,根据业务线或行业等可以对商品进行细分,
如淘宝的商品、天猫的商品、 1688的商品、飞猪旅行的商品、
淘宝海外的商品、天猫国际的商品等。
不同分类的商品,其维度属性可能相同,也可能不同。
比如航旅的商品和普通的淘系商品,都属于商品,
都有商品价格、标题、类型、上架时间、 目等维度属性,
但是航旅的商品除了有这些公共属性外,
还有酒店、 景点、门票、旅行等自己独特的维度属性。
如何设计维度?针对此问题,主要有两种解决方案:
方案1:
是将维度的不同分类实例化为不同的维度,
同时在主维度中保存公共属性。
方案2:
是维护单一维度,包含所有可能的属性。
选择哪种方案?
在数据模型设计过程中需要考虑的因素有很多,
基本不可能满足各个特性指标的最优化。
【设计需要考虑的原则】
1、扩展性:
当源系统、业务逻辑变化时,
能通过较少的成本快速扩展模型,保持核心模型的相对稳定性。
软件工程中的高内聚、低稠合的思想是重要的指导方针之
2、效能:
在性能和成本方面取得平衡。
通过牺牲一定的存储成本,达到性能和逻辑的优化。
3、易用性:
模型可理解性高、访问复杂度低。
用户能够方便地从模型中找到对应的数据表,并能够方便地查询和分析。
根据数据模型设计思想,在对维度进行水平拆分时,主要考虑如下两个依据。
【水平拆分的依据】
1、维度的不同分类的属性差异情况。
当维度属性随类型变化较大时,
将所有可能的属性建立在 个表中是不切合实际的,
也没有必要这样做,此时建议采用方案1 。
定义一个主维度用于存放公共属性;
同时定义多个子维度,其中除了包含公共属性外,还包含各自的特殊属性。
比如在阿里巴巴数据仓库维度体系中,
依据此方法,构建了商品维度、航旅商品维度等。
公共属性一般比较稳定,通过核心的商品维度,保证了核心维度的稳定性;
通过扩展子维度的方式,保证了模型的扩展性。
2、业务的关联程度。
两个相关性较低的业务,稠合在起弊大于利,
对模型的稳定性和易用性影响较大。
比如在阿里巴巴数据仓库维度体系中,
对淘系商品和 1688 商品构建两个维度。
虽然淘系和1688 在底层技术实现上是统一的,
但属于不同的 BU ,业务各自发展在数据仓库层面,
淘系和 688 属于不同的数据集市,一般不会相互调用,
业务分析人员 般只针对本数据集市进行统计分析。
如果设计成 个维度,由于不同 业务各自发展,
1688 业务变更,此维度需要变更,
淘宝业务变更亦然,稳定性很差;
在易用性方面,会给数据使用方造成困扰。
10.2.3 垂直拆分
在维度设计内容中,我们提到维度是维度建模的基础和灵魂,
维度属性的丰富程度直接决定了数据仓库的能力。
在进行维度设计时,依据维度设计的原则,尽可能丰富维度属性,
同时进行反规范化处理。
对于具体实现时可能存在的问题,
【水平拆分的问题】
一是在“水平拆分”中提到的,
由于维度分类的不同而存在特殊的维度属性,
可以通过水平拆分的方式解决此问题。
二是某些维度属性的来源表产出时间较早,
而某些维度属性的来源表产出时间较晚;
或者某些维度属性的热度高、使用频繁,
而某些维度属性的热度低、较少使用或者某些维度属性经常变化,
而某些维度属性比较稳定。
在“水平拆分”中提到的模型设计的三个原则同样适合解决此问题。
出于扩展性、产出时间、易用性等方面的考虑,设计主从维度。
主维表存放稳定 产出时间早、热度高的属性;
从维表存放变化较快、产出时间晚、热度低的属性。
比如在阿里巴巴数据仓库中,
设计了商品维度和商品扩展维度。
其中商品主维度在每日的1:30 左右产出,
而商品扩展维度由于有冗余的产出时间较晚的商品品牌和标签信息 ,
在每3:00 左右产出。
另外,由于商品扩展维度有冗余的库存等变化较快的数据,
对于主维度进行缓慢变化的处理较为重要。
通过存储的冗余和计算成本的增加,
实现了商品主模型的稳定和产出时间的提前,
对于整个数据仓库的稳定和下游应用的产出都有较大意义。
10.2.4 历史归档
阿里巴巴历史截至当前的淘系(含淘宝、天猫和聚划算)商品有几百亿条记录,
在 Max Compute 中,一天的全量数据占用约 6TB 的存储。
面对如此庞大的数据量,
如何设计模型、
如何降低存储、
如何让下游方便获取数据,
成为必须要解决的问题。
对于历史数据,是否存在前台已经不再使用的情况?
答案是肯定的,对于如此庞大的数据量,
现有的技术架构也很难处理。
前台有一套数据归档策略,
比如将商品状态为下架或删除的且最近 31 天未更新的商品归档至历史库,
具体逻辑根据不同。
BU 有不同的算法,且有特殊的规则。
在数据仓库中,
可以借用前台数据库的归档策略,定期将历史数据归档至历史维表。
在实践中,网里巴巴数据仓库设计了商品维表和历史商品维表,
每天将历史数据归档至历史商品维表。
关于归档策略,有以下几种方式。
【归档策略的方式】
归档策略1:同前台归档策略,在数据仓库中实现前台归档算法, 定期对历史数据进行归档。
但存在一些问题,
一是前台归档策略复杂, 实现成本较高
二是前台归档策略可能会经常变化,导致数据仓库归档算法也要随之变化,
维护和沟通成本较高。
此方式适用于前台归档策略逻辑较为简单,且变更不频繁的情况。
归档策略2:同前台归档策略,但采用数据库变更日志的方式。
对于如此庞大的数据量,
阿里巴巴采用的数据抽取策略,
一般是通过数据库binlog 日志解析获取每日增量,
通过增量 merge 全量的方式获取最新的全量数据。
可以使用增量日志的删除标志,作为前台数据归档的标志。
通过此标志对数据仓库的数据进行归档。
此方式不需要关注前台归档策略,简单易行。
但对前台应用的要求是数据库的物理删除只有在归档时才执行,
应用中的删除只是逻辑删除。
归档策略3:数据仓库自定义归档策略。
可以将归档算法用简单、直接的方式实现,
但原则是尽量比前台应用晚归档、少归档。
避免出现数据仓库中已经归档的数据再次更新的情况。
如果技术条件允许,能够解析数据库 binlog日志,
建议使用归档策略2,规避前台归档算法。
具体可以根据自身数据仓库的实际情况进行选择。