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