Greenplum 实时数据仓库实践——数据仓库设计基础
Posted wzy0623
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Greenplum 实时数据仓库实践——数据仓库设计基础相关的知识,希望对你有一定的参考价值。
目录
本篇首先介绍关系数据模型、多维数据模型和Data Vault模型这三种常见的数据仓库模型和与之相关的设计方法,然后讨论数据集市的设计问题,最后说明一个数据仓库项目的实施步骤。规划实施过程是整个数据仓库设计的重要组成部分。
关系模型、多维模型已经有很长的历史,而Data Vault模型相对比较新。它们都是流行的数据仓库建模方式,但又有各自的特点和适用场景。读者在了解了本篇的内容后,可以根据实际需求选择适合的方法构建自己的数据仓库。
2.1 关系数据模型
关系模型是由E.F.Codd在1970年提出的一种通用数据模型。由于关系数据模型简单明了,并且有坚实的数学理论基础,所以一经推出就受到了业界的高度重视。关系模型被广泛应用于数据处理和数据存储,尤其是在数据库领域,现在主流的数据库管理系统几乎都是以关系数据模型为基础实现的。
2.1.1 关系数据模型中的结构
关系数据模型基于关系这一数学概念。在本小节中,解释关系数据模型中的术语和相关概念。为了便于说明,我们使用一个分公司-员工关系的例子。假设有一个大型公司在全国都有分公司,每个员工属于一个分公司,一个分公司有一个经理,分公司经理也是公司员工。分公司-员工关系如图2-1所示。
图2-1 分公司-员工关系
关系
由行和列构成的二维结构,对应关系数据库中的表,如示例中的分公司表和员工表。注意,这种认识只是我们从逻辑上看待关系模型的方式,并不应用于表在磁盘上的物理结构。表的物理存储结构可以是堆文件、索引文件或哈希文件。堆文件是一个无序的数据集合,索引文件中表数据的物理存储顺序和逻辑顺序保持一致,哈希文也称为直接存取文件,是通过一个预先定义好的哈希函数确定数据的物理存储位置。
属性
由属性名称和类型名称构成的顺序对,对应关系数据库中表的列,如地址(Variable Characters)是公司表的一个属性。属性值是属性一个特定的有效值,可以是简单的标量值,也可以是复合数据类型值。
在关系数据模型中,我们把关系描述为表,表中的行对应不同的记录,表中的列对应不同的属性。属性可以以任何顺序出现,而关系保持不变,也就是说,在关系理论中,表中的列是没有顺序的。
属性域
属性的取值范围。每一个属性都有一个预定义的值的范围。属性域是关系模型的一个重要特征,关系中的每个属性都与一个域相关。各个属性的域可能不同,也可能相同。域描述了属性所有可能的值。
域的概念是很重要的,因为它允许我们定义属性可以具有的值的意义。系统可因此获得更多的信息,并且可以拒绝不合理的操作。在我们的例子中,分公司编号和员工编号都是字符串,但显然具有不同的含义,换句话说,它们的属性域是不同的。表2-1列出了分公司-员工关系的一些属性域。
属性 | 属性域的定义 | 含义 |
分公司编号 | 字符:大小为4,范围为B001-B999 | 设置所有可能的分公司编号 |
地址 | 字符:大小为100 | 设置所有可能的地址 |
员工编号 | 字符:大小为5,范围为S0001-S9999 | 设置所有可能的员工编号 |
职位类别 | 管理、技术、销售、运营、产品之一 | 设置所有可能的员工职位类别 |
表2-1 分公司-员工关系的一些属性域
元组
关系中的一条记录,对应关系数据库中的一个表行。元组可以以任何顺序出现,而关系保持不变,也就是说,在关系理论中,表中的行是没有顺序的。
关系数据库
一系列规范化的表的集合。这里的规范化可以理解为表结构的正确性。本节后面会详细讨论规范化问题。
以上介绍了关系数据模型的两组术语:“关系、属性、元组”和“表、列、行”。在这里它们的含义是相同的,只不过前者是关系数据模型的正式术语,而后者是常用的数据库术语。其它可能会遇到的类似术语还有实体(表)、记录(行)、字段(列)等。
关系表的属性
关系表有如下属性:
- 每个表都有唯一的名称。
- 一个表中每个列有不同的名字。
- 一个列的值来自于相同的属性域。
- 列是无序的。
- 行是无序的。
关系数据模型中的键
超键
一个列或者列集,唯一标识表中的一条记录。超键可能包含用于唯一标识记录所不必要的额外的列,我们通常只对仅包含能够唯一标识记录的最小数量的列感兴趣。
候选键
仅包含唯一标识记录所必须的最小数量列的超键。表的候选键有三个属性:
- 唯一性:在每条记录中,候选键的值唯一标识该记录。
- 最小性:具有唯一性属性的超键的最小子集。
- 非空性:候选键的值不允许为空。
在我们的例子中,分公司编号是候选键,如果每个分公司的邮编都不同,那么邮编也可以作为分公司表的候选键。一个表中允许有多个候选键。
主键
唯一标识表中记录的候选键。主键是唯一、非空的。没有被选做主键的候选键称为备用键。对于例子中的分公司表,分公司编号是主键,邮编就是备用键,而员工表的主键是员工编号。
主键的选择在关系数据模型中非常重要,很多性能问题都是由于主键选择不当引起的。在选择主键时,我们可以参考以下原则:
- 主键要尽可能的小。
- 主键值不应该被改变。主键会被其它表所引用。如果改变了主键的值,所有引用该主键的值都需要修改,否则引用就是无效的。
- 主键通常使用数字类型。数字类型的主键要比其它数据类型效率更高。
- 主键应该是没有业务含义的,它不应包含实际的业务信息。无意义的数字列不需要修改,因此是主键的理想选择。大部分关系型数据库支持的自增属性或序列对象更适合当做主键。
- 虽然主键允许由多列组成,但应该使用尽可能少的列,最好是单列。
外键
一个表中的一列或多列的集合,这些列匹配某些其它(也可以是同一个)表中的候选键。注意外键所引用的不一定是主键,但一定是候选键。当一列出现在两张表中的时候,它通常代表两张表记录之间的关系。如例子中分公司表的分公司编号和员工表的所属分公司。它们的名字虽然不同,但却是同一含义。分公司表的分公司编号是主键,在员工表里所属分公司是外键。同样,因为公司经理也是公司员工,所以它是引用员工表的外键。主键所在的表被称为父表,外键所在的表被称为子表。
2.1.2 关系完整性
上一小节讨论了关系数据模型的结构部分,本小节讨论关系完整性规则。关系数据模型有两个重要的完整性规则:实体完整性和参照完整性。在定义这些术语之前,先要理解空值的概念。
空值(NULL)
表示一个列的值目前还不知道或者对于当前记录来说不可用。空值可以意味着未知,也可以意味着某个记录没有值,或者只是意味着该值还没有提供。空值是处理不完整数据或异常数据的一种方式。空值与数字零或者空字符串不同,零和空字符串是值,但空值代表没有值。因此,空值应该与其它值区别对待。空值具有特殊性,当它参与逻辑运算时,结果取决于真值表。每种数据库系统对空值参与运算的规则定义也不尽相同。表2-2到表2-4分别为大部分主流数据库系统(Oracle、mysql、PostgreSQL、Greenplum等)的非、与、或逻辑运算真值表。
TRUE | FALSE | NULL | |
NOT | FALSE | TRUE | NULL |
表2-2 逻辑非运算
AND | TRUE | FALSE | NULL |
TRUE | TRUE | FALSE | NULL |
FALSE | FALSE | FALSE | FALSE |
NULL | NULL | FALSE | NULL |
表2-3 逻辑与运算
OR | TRUE | FALSE | NULL |
TRUE | TRUE | TRUE | TRUE |
FALSE | TRUE | FALSE | NULL |
NULL | TRUE | NULL | NULL |
表2-4 逻辑或运算
在我们的例子中,如果一个分公司的经理离职了,新的经理还没有上任,此时公司经理列对应的值就是空值。有了空值的定义,就可以定义两种关系完整性规则了。
实体完整性
在一个基本表中,主键列的取值不能为空。基本表指的是命名的表,其中的记录物理地存储在数据库中,与之对应的是视图。视图是虚拟的表,它只是一个查询语句的逻辑定义,其中并没有物理存储数据。
从前面介绍的定义可知,主键是用于唯一标识记录的最小列集合。也就是说,主键的任何子集都不能提供记录的唯一标识。空值代表未知,无法进行比较。如果允许空值作为主键的一部分,就意味着并不是所有的列都用来区分记录,这与主键的定义矛盾,因此主键必须是非空的。例如,分公司编号是分公司表的主键,在录入数据的时候,该列的值不能为空。
参照完整性
如果表中存在外键,则外键值必须与主表中的某些记录的候选键值相同,或者外键的值必须全部为空。在图2-1中,员工表中的所属分公司是外键。该列的值要么是分公司表的分公司编号列中的值,要么是空(如新员工已经加入了公司,但还没有被分派到某个具体的分公司时)。
业务规则
定义或约束组织的某些方面的规则。业务规则的例子包括属性域和关系完整性规则。属性域用于约束特定列能够取的值。大部分主流数据库系统(Oracle、MySQL、PostgreSQL、Greenplum等)支持叫做check的约束,也用于定义列中可以接受的值,但这种约束是定义在属性域之上的,比属性域的约束性更强。例如,员工表的性别列就可以加上check约束,使它只能取有限的几个值。
2.1.3 关系数据库语言
关系语言定义了允许对数据进行的操作,包括从数据库中更新或检索数据所用的操作以及改变数据库对象结构的操作。关系数据库的主要语言是SQL语言。
SQL是Structured Query Language的缩写,意为结构化查询语言。SQL已经被国际标准化组织(ISO)进行了标准化,使它成为正式的和事实上的定义和操纵关系数据库的标准语言。SQL语言又可分为DDL、DML、DCL、TCL四类。
DDL是Data Definition Language的缩写,意为数据定义语言,用于定义数据库结构和模式。典型的DDL有create、alter、drop、truncate、comment、rename等。
DML是Data Manipulation Language的缩写,意为数据操纵语言,用于检索、管理和维护数据库对象。典型的DML有select、insert、update、delete、merge、call、explain、lock等。
DCL是Data Control Language的缩写,意为数据控制语言,用于授予和回收数据库对象上的权限。典型的DCL有grant和revoke。
TCL是Transaction Control Language的缩写,意为事务控制语言,用于管理DML对数据的改变。它允许一组DML语句联合成一个逻辑事务。典型的TCL有commit、rollback、savepoint、set transaction等。
2.1.4 规范化
关系数据模型的规范化是一种组织数据的技术。规范化方法对表进行分解,以消除数据冗余,避免异常更新,提高数据完整性。
不规范化带来的问题
没有规范化,数据的更新处理将变得困难,异常的插入、修改、删除数据的操作会频繁发生。为了便于理解,来看下面的例子。
假设有一个名为employee的员工表,它有九个属性:id员工编号,name员工姓名,mobile电话,zip邮编,province省份,city城市,district区县,deptNo所属部门编号,deptName所属部门名称,表中的数据如表2-5所示。
id | Name | Mobile | zip | province | city | district | deptNo | deptName |
101 | 张三 | 13910000001 13910000002 | 100001 | 北京 | 北京 | 海淀区 | D1 | 部门1 |
101 | 张三 | 13910000001 13910000002 | 100001 | 北京 | 北京 | 海淀区 | D2 | 部门2 |
102 | 李四 | 13910000003 | 200001 | 上海 | 上海 | 静安区 | D3 | 部门3 |
103 | 王五 | 13910000004 | 510001 | 广东省 | 广州 | 白云区 | D4 | 部门4 |
103 | 王五 | 13910000004 | 510001 | 广东省 | 广州 | 白云区 | D5 | 部门5 |
表2-5 非规范化的员工表
由于此员工表是非规范化的,我们将面对如下的问题。
- 修改异常:上表中张三有两条记录,因为他隶属两个部门。如果我们要修改张三的地址,必须修改两行记录。假如一个部门得到了张三的新地址并进行了更新,而另一个部门没有,那么此时张三在表中会存在两个不同的地址,导致了数据不一致。
- 新增异常:假如一个新员工加入公司,他正处于入职培训阶段,还没有被正式分配到某个部门,如果deptNo字段不允许为空,我们就无法向employee表中新增该员工的数据。
- 删除异常:假设公司撤销了D3这个部门,那么在删除deptNo为D3的行时,会将李四的信息也一并删除。因为他只隶属于D3这一个部门。
为了克服这些异常更新,我们需要对表进行规范化设计。规范化是通过应用范式规则实现的。最常用的范式有第一范式(1NF)、第二范式(2NF)、第三范式(3NF)。
第一范式(1NF)
表中的列只能含有原子性(不可再分)的值。
上例中张三有两个手机号存储在mobile列中,违反了1NF规则。为了使表满足1NF,数据应该修改为如表2-6所示。
id | name | mobile | zip | province | city | district | deptNo | deptName |
101 | 张三 | 13910000001 | 100001 | 北京 | 北京 | 海淀区 | D1 | 部门1 |
101 | 张三 | 13910000002 | 100001 | 北京 | 北京 | 海淀区 | D1 | 部门1 |
101 | 张三 | 13910000001 | 100001 | 北京 | 北京 | 海淀区 | D2 | 部门2 |
101 | 张三 | 13910000002 | 100001 | 北京 | 北京 | 海淀区 | D2 | 部门2 |
102 | 李四 | 13910000003 | 200001 | 上海 | 上海 | 静安区 | D3 | 部门3 |
103 | 王五 | 13910000004 | 510001 | 广东省 | 广州 | 白云区 | D4 | 部门4 |
103 | 王五 | 13910000004 | 510001 | 广东省 | 广州 | 白云区 | D5 | 部门5 |
表2-6 满足1NF的员工表
第二范式(2NF)
第二范式要同时满足下面两个条件:满足第一范式;没有部分依赖。例如,员工表的一个候选键是id,mobile,deptNo,而deptName依赖于deptNo,同样name仅依赖于id,因此不是2NF的。为了满足第二范式的条件,需要将这个表拆分成employee、dept、employee_dept、employee_mobile四个表,如表2-7至表2-10所示。
id | name | zip | province | city | District |
101 | 张三 | 100001 | 北京 | 北京 | 海淀区 |
102 | 李四 | 200001 | 上海 | 上海 | 静安区 |
103 | 王五 | 510001 | 广东省 | 广州 | 白云区 |
表2-7 满足2NF的员工表
deptNo | deptName |
D1 | 部门1 |
D2 | 部门2 |
D3 | 部门3 |
D4 | 部门4 |
D5 | 部门5 |
表2-8 满足2NF的部门表
id | deptNo |
101 | D1 |
101 | D2 |
102 | D3 |
103 | D4 |
103 | D5 |
表2-9 满足2NF的员工-部门表
id | mobile |
101 | 13910000001 |
101 | 13910000002 |
102 | 13910000003 |
103 | 13910000004 |
表2-10 满足2NF的员工-电话表
第三范式(3NF)
第三范式要同时满足下面两个条件:满足第二范式;没有传递依赖。例如,员工表的province、city、district依赖于zip,而zip依赖于id,换句话说,province、city、district传递依赖于id,违反了3NF规则。为了满足第三范式的条件,可以将这个表拆分成employee和zip两个表,如表2-11、表2-12所示。
id | name | zip |
101 | 张三 | 100001 |
102 | 李四 | 200001 |
103 | 王五 | 510001 |
表2-11 满足3NF的员工表
zip | province | City | District |
100001 | 北京 | 北京 | 海淀区 |
200001 | 上海 | 上海 | 静安区 |
510001 | 广东省 | 广州 | 白云区 |
表2-12 满足3NF的地区表
在关系数据模型设计中,一般需要满足第三范式的要求。如果一个表有良好的主外键设计,就应该是满足3NF的表。规范化带来的好处是通过减少数据冗余提高更新数据的效率,同时保证数据完整性。然而,我们在实际应用中也要防止过度规范化的问题。规范化程度越高,划分的表就越多,在查询数据时越有可能使用表连接操作。而如果连接的表过多,会影响查询的性能。关键的问题是要依据业务需求,仔细权衡数据查询和数据更新的关系,制定最适合的规范化程度。还有一点需要注意的是,不要为了遵循严格的规范化规则而修改业务需求。
2.1.5 关系数据模型与数据仓库
关系数据模型可以提供高性能的数据更新操作,能很好地满足事务型系统的需求,这点毫无疑问。但是对于查询与分析密集型的数据仓库系统还是否合适呢?对这个问题的争论由来已久,基本可以分为Inmon和Kimball两大阵营,Inmon阵营是应用关系数据模型构建数据仓库的支持者。
Inmon方法是以下面这些假设的成立为前提的。
- 假设数据仓库是以企业为中心的,初始的数据能够为所有部门所使用。而最终的数据分析能力是在部门级别体现,需要使用数据集市对数据仓库中的数据做进一步处理,以便为特定的部门定制它们。
- 数据仓库中的数据不违反组织制定的任何业务规则。
- 必须尽可能快地把新数据装载进数据仓库,这意味着需要简化数据装载过程或减少数据的装载量。
- 数据仓库的建立必须从一开始就被设计成支持多种BI技术,这就要求数据仓库本身所使用的技术越通用越好。
- 假设数据仓库的需求一定会发生变化。它必须能完美地适应其数据和数据结构的变化。
基于这些假设,使用关系数据模型构建数据仓库的优势和必然性就比较明显了。
非冗余性
为适应数据仓库有限的装载周期和海量数据,数据仓库数据模型应该包含最少量的数据冗余。冗余越少,需要装载的数据量就越少,装载过程就越快。另外,数据仓库的数据源一般是事务型系统,这些系统通常是规范化设计的。如果数据仓库使用相同的数据模型,意味着数据转换的复杂性可能会降低,同样可以加快数据装载速度。
稳定性
由于数据仓库的需求会不断变化,我们需要以一种迭代的方式建立数据仓库。众所周知,组织中最经常变化的是它的处理过程、应用和技术,如果依赖于这三个因素中的任何一个建立数据模型,当它们发生改变时,肯定要对数据模型进行彻底地修改。为了避免这个问题,关系数据模型的通用性正是用武之地。另一方面,由于变化不可避免,数据仓库模型应该能比较容易地将新的变化合并进来,而不必重新设计已有的元素和已经实现的实体。
一致性
数据仓库模型最本质的特点是保证作为组织最重要资源的数据的一致性。而确保数据一致性正是关系数据模型的特点之一。
灵活性
数据仓库最重要的一个用途是作为坚实的、可靠的、一致的数据基础为后续的报表系统、数据分析、数据挖掘或BI系统服务。数据模型还必须支持为组织建立的业务规则。这就意味着数据模型必须比简单的平面文件功能更强。为此关系数据模型也是最佳选择之一。
关系数据模型已被证明是可靠的、简单的数据建模方法。应用其规范化规则,将产生一个稳定的、一致的数据模型。该模型支持由组织制定的政策和约定的规则,同时为数据集市分析数据提供了更多的灵活性,结果数据库存储以及数据装载方面也是最有效的。
当然,任何一种数据模型都不可能是完美无瑕的。关系数据模型的缺点也很明显,它需要额外建立数据集市的存储区,并增加相应的数据装载过程。另外,对数据仓库的使用强烈依赖于对SQL语言的掌握程度。
2.2 维度数据模型
维度数据模型简称维度模型(Dimensional modeling,DM),是一套技术和概念的集合,用于数据仓库设计。不同于关系数据模型,维度模型不一定要引入关系数据库。在逻辑上相同的维度模型,可以被用于多种物理形式,比如维度数据库或是简单的平面文件。根据数据仓库大师Kimball的观点,维度模型是一种趋向于支持最终用户对数据仓库进行查询的设计技术,是围绕性能和易理解性构建的。尽管关系模型对于事务处理系统表现非常出色,但它并不是面向最终用户的。
事实和维度是两个维度模型中的核心概念。事实表示对业务数据的度量,而维度是观察数据的角度。事实通常是数字类型的,可以进行聚合和计算,而维度通常是一组层次关系或描述信息,用来定义事实。例如,销售金额是一个事实,而销售时间、销售的产品、购买的顾客、商店等等都是销售事实的维度。维度模型按照业务流程领域即主题域建立,例如进货、销售、库存、配送等。不同的主题域可能共享某些维度,为了提高数据操作的性能和数据一致性,需要使用一致性维度,例如几个主题域间共享维度的拷贝。术语“一致性维度”源自Kimball,指的是具有相同属性和内容的维度。
2.2.1 维度数据模型建模过程
维度模型通常以一种被称为星型模式的方式构建。所谓星型模式,就是以一个事实表为中心,周围环绕着多个维度表。还有一种模式叫做雪花模式,是对维度做进一步规范化后形成的。本节后面会讨论这两种模式。一般使用下面的过程构建维度模型:
- 选择业务流程
- 声明粒度
- 确认维度
- 确认事实
这种使用四步设计法建立维度模型的过程,有助于保证维度模型和数据仓库的可用性。
选择业务流程
确认哪些业务处理流程是数据仓库应该覆盖的,是维度方法的基础。因此,建模的第一个步骤是描述需要建
以上是关于Greenplum 实时数据仓库实践——数据仓库设计基础的主要内容,如果未能解决你的问题,请参考以下文章