数据仓库系列(14):维度设计

(一)维度设计的基础知识

在建设以Hadoop为技术核心的数据仓库时,维度建模是目前应用最广泛的建模方法论,虽然无法说它一定是最合适的,但针对维度建模所涉及的超大规模平台建设已经有了比较成功的应用案例。因此针对维度建模中最基本的维度与事实的概念,需要有一定比较深入的了解,以理解在超大规模平台下如何使用和维护。

维度是维度建模最重要的建设项目,是描述平台表及业务过程的重要表述方式。通常一张维度表是一个主题的统称,使用主键来标识其唯一性,并用于与事实表进行唯一性的关联。维度表中所包含的列是维度的属性,用于描述这张表的约束条件、属性标签等信息。

提前说明一下,本文阅读起来比较枯燥,建议谨慎阅读。

(二)维度设计的基础方法

维度信息的制定有如下几种方式:

1. 提取产品文档中的名词信息,例如客户、落地页、追踪ID等;

2. 根据系统设定自动生成维度信息,例如用户维度对应了行业、地区、公司名称、代理商、预算等维度属性;

3. 根据历史积淀进行设定,例如系统设定中,用户可以创建计划,计划下又包括了创意、关键词、地域等信息,那么设定创意维度表,就要主动向上追溯,包含计划、用户维度属性。

 

一次典型的维度设计过程说明如下:

1. 选择维度或新建维度,接到需求时,首先确定对应的统计信息在已有的数据仓库中是否有维度表,如果有,本着维度一致性的原则,可以复用这张表;如果没有,则重新创建一张;

2. 确定主维度表,根据当前统计的需求,定下主键;

3. 确定相关维表,通过对系统业务过程的梳理,确定该主键的关联关系,例如设定创意维度表,就要主动向上追溯,包含计划、用户的关联关系;

4. 确定维度属性,根据主键及关联维表,选择本次业务过程中会用到、及未来可能扩展统计会用到的维度,整合到新的维度表中,形成维度属性。

 

维度属性需要遵循以下几点原则:

1. 维度属性尽可能丰富:在大数据环境下,适当冗余一些维度属性,对于下游统计的一致性与便捷性有极大的帮助;

2. 维度属性的注释尽可能丰富:维度表不是事实表,对于业务过程的理解至关重要,添加足够多的文字描述信息,对于跨团队的使用与后期维护均有极大的帮助;

3. 针对特定业务情况有成熟的处理方式:例如部分字段既可以作为维度,也可以作为事实,以金额为例,在通常情况下,广告系统会统计用户的消费情况,但存在特殊逻辑,例如通过消费金额字段可以统计消费区间内的用户数量,此时可以视情况将消费金额当作一个维度信息。

(三)维度设计的反规范化与一致性问题

以淘宝的例子来说明雪花模型的反规范化问题,如下图所示:

假设系统是按照上图的方式进行组织和存储的,当我们需要对某类条目进行更新时,必须同时更新商品表和类目表,由于商品与类目是一对多的关系,且表中数据量很大,那么一次更新操作就需要同时更新上百万条记录,对于系统的处理压力来说非常大。因此为了更方便的来更新一些经常变化的维度,并降低系统处理的复杂度,我们常常将属性层次合并到单个维度表中,如下图所示:

在上图所示的情况下,我们将类目维度添加了“类目”前缀,将行业维度添加了“行业”前缀……尽管模型阅读起来要困哪一些,但并没有丢失任何信息,不论是查询还是更新,一次查询SQL或者一个MapReduce过程就可以处理全部信息,效能上大了很多。

因此,雪花模式虽然阅读清晰、节约存储空间,但在Hadoop三备份的机制下,节约的存储空间对于系统的提升并不大,反而增加了计算的负担。在实际应用中,维度表总是会设计的冗余一些,以换取更高的查询和更新性能。

但上述反规范化的处理方式会带来一致性的问题。由于很多指标的统计需要跨主题进行,像交易订单不仅要统计金额,还需要统计当前页面的PV与UV信息,这种查询称之为交叉探查。如果在查询过程中存在重复的维度,就会出现查询错误的情况。

例如有两个主题,一个是网页日志,另一个是交易日志,统计要求分别统计一个订单的网页统计指标(PV、UV)和它的交易统计指标(下单数、交易金额),当订单维度包含了已成交订单和未成交订单两种类型时,要求将订单的统计指标拆分成已成交订单和未成交订单两个维度,这时网页指标的维度表中并没有这两个维度的属性,因此这个统计就出现了问题,无法完成。

假设维度统计设计的出现了问题,那么上述这个例子就会一而再再而三的发生,因为新来的产品或分析人员不懂其中的内在关系。

那么通过哪些方式可以避免反规范化后的一致性问题呢?有如下三种:

1. 设计公共维度表:将主要的大类设计成维度表,以淘宝系为例:商品、买家、卖家、类目等维度表有且只有一个,所有公共维度的统计都需要基于这些公共维度表,这时交叉探查就不会存在问题;

2. 一致性上卷:假设有两张维度表,其中一张维度表的维度属性,都是另一张维度表的维度属性的子集,且两个维度表的公共属性相同。仍然以淘宝系为例,假设存在商品维度表和类目维度表,其中类目维度表的属性是商品维度表的维度属性的子集,且公共属性相同,这时做交叉探查也不会存在问题;

3. 交叉属性:两张维度表有部分相同的维度属性,而查询仅限于在相同的维度属性上做交叉探查,这种情况非常需要程序员来注意,有必要的话在元数据平台上尽可能的将这些信息标注出来,出现查询错误的概率会大幅度下降。

(四)维度设计的整合方式

在对维度设计的基本方式和常见处理方法有了基本了解之后,把思路收回来,从更高层次的角度上来看待数据仓库中的 维度设计。假设你接手了搭建一个新的数据仓库平台,所有的工作你可以重新设计,那么针对数据仓库的维度设计,你应该从何下手呢?

答案有两个,一个是知道如何将分散的业务指标整合起来,另一个是熟悉如何将整合起来的每一个主题重新按照规则拆分下去。插句题外话,前文提到了架构设计的两种方式:自顶向下、自底向上,这两种设计架构的方式始终贯穿于数据仓库平台的建设之中,有条件的数据开发人员最好亲自动手去设计和实现一个mini版的数据仓库,这样对于很多的架构方法论才能有一个切身的体会,而不是泛泛而谈。

这一部分主要阐述维度设计应该如何整合业务指标。

维度设计的整合方式,出发点是针对繁杂多变的业务指标,做一个有效的整合。繁杂多变主要来源于两个方面:

1. 开发人员在编码、命名习惯、度量单位上有巨大分歧,编码与命名规范尚好理解,度量单位最典型的是金额,由于现实中最小的货币单位是分,因而很多公司采用了分作为金额的最小度量单位,但很多公司因为数据库设计等问题,需要在最小度量单位后加入1-N个0,来讲字段的格式补充完整,甚至于极端业务场景下需要统计小于分的金额,这就需要根据所在公司的具体情况进行考虑;

2. 出于架构的技术结构和扩展性考虑,现在的互联网公司没有统一技术结构的说法,基本上都是多种技术架构共存的情况,例如平台部分依然离不开传统的关系型数据库(Mysql、Oracle、PostgreSql),但大数据部门都采用Nosql的数据库来存储(HBase、Mongodb、Tair),当然最常用的网页日志大多以Hive表的形式进行存储,部分需要高速性能的数据还会以列存的形式存在(Parquent格式之于Impala),不同技术架构、不同数据量的业务场景对于维度设计的适用场景也不尽相同。

 

但还是存在了很多共识层面上的整合,具体有如下几种:

1. 命名规范,例如表名、字段名的统一;

2. 字段类型,例如整型和字符串的区分和统一;

3. 计算方式,例如PV、UV、消费金额概念的统一;

4. 业务涵义,本着高内聚、低耦合的理念,将业务内在关系大、对于数据来源高度统一的表进行整合。

因此针对主题信息相近的信息,根据部门和数据量的不同,尽可能将相近的维度表设计到同一种技术架构下,并设定相应的规范。

 

整合通常由两种方式来设计:垂直整合和水平整合,相关涵义如下:

1. 垂直整合:即不同的来源表包含相同的数据集,只是存储的信息不同,尽量整合在一起。例如行业在统计系统中有多个表:行业基础信息表、行业用户统计表、行业历史变化表,根据维度设计的方法论,都应该整合到行业的维度表中,尽量丰富行业表的维度属性;

2. 水平整合:即不同的来源表包含不同的数据集,不同的子集之间无交叉或部分交叉。例如阿里平台非常大,仅会员就包括了淘宝会员、1688会员、支付宝会员等,是否应该整合到同一张会员表中呢?首先考虑各个会员体系之间是否存在交叉的维度属性,有的话需要进行去重;其次考虑他们之间的主键是否会存在冲突,如果冲突可以设置一种“超自然键”,以虚拟的方式将各个表整合起来。

(五)维度设计的拆分方式

既然上一部分提到了维度的整合,那么针对已经成型的主题信息,就需要考虑维度的拆分了。通常来说维度有两种设计方式,一种是将维度的不同子维度设计成单独的子维度表,同时在主维度表中保存公共属性;另一种是维护单一的维度表,将所有的维度属性都保存在一起。选择何种方式,我们可以从扩展性、使用效能及易用性等方面进行考虑:

1. 根据维度的属性差异情况进行考虑:当维度属性变化较大时,将所有的维度属性放在同一张表里并不合适,因而通常采用定义一个主维度用于存放公共属性,定义多个子维度以保存各自的特殊属性;

2. 根据业务的关联程度进行考虑:两个相关性较低的业务关联在一起,弊肯定大于利,本着高内聚、低耦合的思想,应该设计成两个不同主题域的主维度表,以示区分;

3. 根据维度属性的使用频率进行考虑:部分公共主维度会被频繁统计,并且变更的可能性较小,但很多根据业务需求新添加的维度信息,变化速度快,且更新频繁,因此可以设计成主从的形式,主维度表存储基本无变化的公共维度属性,子维度表存储变化较快的新子维度属性,对于系统的稳定性意义颇大。

(六)维度设计的历史变化

维度表与事实表比起来,具备更新较慢的特点,但随着时间推移与业务发展,依然有更新和变化的需求,因此在大部分情况下,保留历史数据并无太大的分析意义,但特殊性况下,依然会要求保留历史的维度数据与事实数据。

在Kimball的理论中,有三种处理历史变化的相关方式:

1. 重写维度值:这种方式不保留历史数据,始终只存储最新的数据;

2. 插入新的维度行:这种方式保留历史数据,将维度值变化前的事实数据与过去的维度值进行关联,维度值变化后的事实数据与当前的维度值进行关联,从而得到跨段的统计数据;

3. 添加维度列:由于采用第二种方式不能够将变化前及变化后的数据进行统一,因此通过新增维度列的方式,将新的数据统计到新的列值上,根据需求查询不同的列得到现在或者是历史数据。

(七)题外话

针对维度设计,到此为止基本上能够说清相关的设计思想,针对阿里系提到的很多特殊情况,例如快照、极限、微型、递归、行为、多值、杂项等场景,多用于特殊业务场景,在笔者从事的广告数据统计方面基本上涉及不到,这里也不做过多介绍。

发布了19 篇原创文章 · 获赞 0 · 访问量 891

猜你喜欢

转载自blog.csdn.net/gaixiaoyang123/article/details/103993687