数据仓库模型建设规范
数据仓库不同于日常的信息系统开发,除了遵循其他系统开发的需求、分析、设计、测试等通常的软件生命周期之外,它还涉及到企业信息数据的集成,大容量数据的阶段处理和分层存储,数据仓库的模式选择等等,因此数据仓库的模型设计异常重要,这也是关系到数据仓库项目成败的关键。
物理模型就像大厦的基础架构,就是通用的业界标准,无论是一座摩天大厦也好,还是茅草房也好,在架构师的眼里,他只是一所建筑,地基—层层建筑—封顶,这样的工序一样也不能少,关系到住户的安全,房屋的建筑质量也必须得以保证,唯一的区别是建筑的材料,地基是采用钢筋水泥还是石头,墙壁采用木质还是钢筋水泥或是砖头;当然材料和建筑细节还是会有区别的,视用户给出的成本而定;还有不可忽视的一点是,数据仓库的数据从几百GB到几十TB不等,即使支撑这些数据的RDBMS无论有多么强大,仍不可避免地要考虑数据库的物理设计。
数据仓库建模的设计目标是模型的稳定性、自适应性和可扩展性。为了做到这一点,必须坚持建模的相对独立性、业界先进性原则。
1. 数聚模型架构
在数聚项目实施过程,我们一般将数据仓库系统的数据划分为如下图所示几个层次。
1.1. 数据架构图
1.2. 架构工作方法规范
数据类型 | 抽取方式 | 转换方式 | 加载方式 | 表类型 | 变化类型 | 加载过程 |
1.有时间戳 | 增量变化抽取 | 清洗转换
| 增量变化加载 | 维表 | 新增 | 新增代理键。插入记录 |
修改 | 如果须保留历史,新增代理键。插入记录 | |||||
删除 | 若为逻辑删除,可等同修改,或在抽取时过滤。 | |||||
事实表 | 新增 | 根据流水号删除目标表数据,查找代理键, 然后再加载增量变化数据. | ||||
修改 | ||||||
删除 | 一般来说,事实表数据不物理删除, | |||||
1.无时间戳 | 全量抽取 | 清洗转换 | 全量加载 | 维表 | 只适合系统初始化数据加载, | |
事实表 | 查找对应代理键,全部加载, | |||||
清洗转换 添加时间戳 | 增量变化加载 | 维表 | 新增 | 新增代理键。插入记录 | ||
修改 | 如果须保留历史,新增代理键。插入记录 | |||||
删除 | 维表不处理被删除的维度记录。 | |||||
事实表 | 新增 | 根据事务流水号,删除目标表。 | ||||
修改 | ||||||
删除 | 根据事务流水号,删除目标表. |
1.3. 准备层L0
1.3.1. 主要数据结构
临时表:从数据源抽取,直接落地到临时表。临时表总是保存这次抽取的数据,不保留历史数据。也就是说,如果是全量抽取的话,就是源系统整个表的数据,如果是增量抽取的话,就是自从上次修改后的数据。
接口表:从临时表,经过清洗、转换到达接口表。接口表保存历史数据,也就是说,如果是全量抽取的话,就是源系统整个表的数据,如果是增量抽取的话。
接口表里面也是源系统整个表的数据。
转换表:为了进行清洗和转换建立的中间辅助表。
1.3.2. 命名规范
临时表:L0_TMP_源系统_具体业务 或 L0_TMP_业务主题_具体业务(对单一源)
举例:L0_TMP_POS_SALESORDER
接口表:L0_DCI_业务主题_具体业务表
举例:L0_DCI_SALES_SALESORDER
转换表:L0_MAP_具体业务表
举例:L0_MAP_SALES
1.3.3. 开发工作
l 开发数据抽取接口,落地TMP区
l 开发数据清洗转换程序,落地DCI区,多源系统进行合并
l 开发数据装载程序,装载到L1层
1.4. 原子层L1
1.4.1. 主要数据结构
维 度 表:整个数据仓库一致的维度
代 码 表:维度属性,非维度代码等。
原子事实表:根据业务主题,形成原子事实表
汇总事实表:根据分析主题,业务主题形成合并或汇总的事实表。
1.4.2. 命名规范
维 度 表:DW_DIM_维度。
举例:组织维 DW_DIM_ORG 日期维 DW_DIM_DATE.
代 码 表:DW_CODE_代码。
举例:性别 DW_CODE_GENDER
原子事实表:L1_DW_FACT_分析主题_具体分析
汇总事实表:L1_DM_FACT_分析主题_具体分析
1.4.3. 开发工作
l 维护聚集。
l 衍生计算,二次指标计算。
1.5. 应用层L2
1.5.1. 主要数据结构
宽 表: 根据需求,从L1层抽取成宽表,表现形式为固定报表,仪表盘等等。
立 方 体: 根据分析主题,从L1生成OLAP立方体。
视 图: 根据需要,从L1,L0层产生L2层的视图。
前端应用,不仅仅可以利用L2层的数据结构,还可以利用L1层的数据结构。对于源系统,还可以利用L0层的DCI区数据,可以做详单和明细查询。
1.5.2. 命名规范
宽 表: L2_FACT_【应用主题】_【分析主题】_应用。
举例:L2_FACT_FIN_ZCFZB (财务->资产负债表
立 方 体: 根据分析主题,从L1生成OLAP立方体。
视 图: 根据需要,从L1,L0层产生L2层的视图。如明细单。
举例:L2_VIEW_原L1层表。
1.5.3. 开发工作
数据从L1层经过计算,汇总,根据前端分析需求,形成可以有效支撑前端应用查询的结构。
2. 建模方法
要成功地建立一个数据仓库,必须有一个合理的数据模型。数据仓库建模在业务需求分析之后开始,是数据仓库构造的正式开始。在创建数据仓库的数据模型时应考虑:
满足不同层次、用户的需求;兼顾查询效率与数据粒度的需求;支持用户需求变化;避免业务运营系统性能影响;提供可扩展性。数据模型的可扩展性决定了数据仓库对新的需求的适应能力,建模既要考虑眼前的信息需求,也要考虑未来的需求。
目前两类主流的数据仓库模型分别是由Inmon提出的企业级数据仓库模型和由Kimball提出的多维模型。Inmon提出的企业级数据仓库模型采用第三范式(3NF),先建立企业级数据仓库,再在其上开发具体的应用。企业级数据仓库固然是我们所追求的目标,但在缺乏足够的技术力量和数据仓库建设经验的情况下,按照这种模型设计的系统建设过程长,周期长,难度大,风险大,容易失败。这种模型的优点是信息全面、系统灵活。由于采用了第三范式,数据存储冗余度低、数据组织结构性好、反映的业务主题能力强以及具有较好的业务扩展性等,但同时会存在大量的数据表,表之间的联系比较多,也比较复杂,跨表操作多,查询效率较低,对数据仓库系统的硬件性能要求高等问题。另一方面,数据模式复杂,不容易理解,对于一般计算机用户来说,增加了理解数据表的困难。
Kimball提出的多维模型降低了范式化,以分析主题为基本框架来组织数据。以维模型开发分析主题,这样能够快速实施,迅速获得投资回报,在取得实际效果的基础上,再逐渐增加应用主题,循序渐进,积累经验,逐步建成企业级数据仓库。这也可以说是采用总线型结构先建立数据集市,使所有的数据集市具有统一的维定义和一致的业务事实,这种方法融合了自下而上和自上而下两种设计方法的思想。这种模型的优点是查询速度快,做报表也快;缺点是由于存在大量的预处理,其建模过程相对来说就比较慢。当业务问题发生变化,原来的维不能满足要求时,需要增加新的维。由于事实表的主码由所有维表的主码组成,所以这种维的变动将是非常复杂、非常耗时的。而且信息不够全面、系统欠灵活、数据冗余多。
本规范我们主要针对维度建模的方法来阐述规范。
2.1. 维度建模
多维数据建模以直观的方式组织数据,并支持高性能的数据访问。每一个多维数据模型由多个多维数据模式表示,每一个多维数据模式都是由一个事实表和一组维表组成的。多维模型最常见的是星形模式。在星形模式中,事实表居中,多个维表呈辐射状分布于其四周,并与事实表连接。
位于星形中心的实体是指标实体,是用户最关心的基本实体和查询活动的中心,为数据仓库的查询活动提供定量数据。每个指标实体代表一系列相关事实,完成一项指定的功能。位于星形图星角上的实体是维度实体,其作用是限制用户的查询结果,将数据过滤使得从指标实体查询返回较少的行,从而缩小访问范围。每个维表有自己的属性,维表和事实表通过关键字相关联。
使用星形模式主要有两方面的原因:提高查询的效率。采用星形模式设计的数据仓库的优点是由于数据的组织已经过预处理,主要数据都在庞大的事实表中,所以只要扫描事实表就可以进行查询,而不必把多个庞大的表联接起来,查询访问效率较高。同时由于维表一般都很小,甚至可以放在高速缓存中,与事实表作连接时其速度较快;便于用户理解。对于非计算机专业的用户而言,星形模式比较直观,通过分析星形模式,很容易组合出各种查询。
2.2. 建模步骤
第一步:选取建模的业务过程
设计过程的第一步是确定要建模的业务过程或者度量事件。业务过程是在业务需求收集过程明确下来。
在很多的生产活动中,存在着很多价值链,这些价值链就是有一系列的业务过程来组成的。比如在供应链管理中。存在着下面的业务过程:
原材料购买
原材料交货
原材料库存
材料账单
生产制造
将产品运到仓库
制成品库存
客户订单
为客户送货
货品计价
付款
退货
第二步:定义模型的粒度
业务过程被确定下来后,就建模师就必须声明事实表的粒度。清楚地定义事实表的行到底代表什么在提出业务过程维度模型的过程至关重要。如果没有在事实表的粒度上达成一致,那么设计过程就不可能成功地向前推进。
第三步:选定维度
一旦事实表的粒度已经稳固地确定下来,对维的选择就相当简单了。也正是在此时,就可以开始考虑外键的问题了。一般来说,粒度本身就能够确定一个基本或者最小的维度集合,设计过程就是在此基础上添加其他维。这些维在已经声明的事实表粒度都有一个唯一对应的值。
第四步:确定事实
四步设计过程的最后一步是仔细选择适用于业务过程的事实和指标。事实可以从度量事件中采用物理手段捕捉,或者也可以从这些度量中导出。对于事实表粒度来说,每个事实都是必须设计存在的,不要将那些明确声明的粒度不相匹配的其他时间段的事实或者其他细节层次的事实混杂进来。
3. 维度表设计
维度表包含内容:
1) 代理键:整型,不可重复,唯一标识每一条记录,不包含任何商业信息。(必选)
2) 代理键有效开始时间和结束时间。(必选)
3) 当前有效标志。(必选)
4) 主键:传统意义的业务键,包含相应的商业信息,如员工编号。(必选)
5) 名称:数据分析时显示的内容,如员工名称等;(必选)
6) 排序键:自定义序列。(可选)
7) 自定义汇总:利用自定义表达式进行特定的数据运算。可选)
8) 父键:父子维度中用来标识主键的上级。(可选)
9) 一元运算符:在父子维度中用来定义上下级的汇总关系。(可选)(详细)
10) 属性:属性包含有关维度的信息。例如,Customer 维度可以包含 Name、Phone Number、Gender、City、State 等属性。属性通过属性层次结构显示出来。维度中的属性层次结构同时包含可选的 (All) 级别和该属性的非重复成员。例如,Customer 维度可以包含具有两个级别的 Name 属性层次结构:(All) 级别以及为每个姓名包含一个成员的级别。父子层次结构的处理方式有所不同。属性不一定要具有属性层次结构。如果未创建属性层次结构,多维数据集的空间将与属性无关。例如,通常不会为 Phone Number 属性创建属性层次结构,因为通常不会按电话号码导航维度。如果没有为属性创建属性层次结构,则该属性可用作成员属性,但不能用作用户层次结构中的级别。属性可以通过前端展示软件进行展现。(可选)
11) 属性层次结构:属性层次结构完全定义多维数据集的空间。多维数据集是由多维数据集的属性层次结构的交集产生的多维空间。(可选)
3.1. 时间维度
时间维度是必不可少的一个维度,可以参考如下的模板:
Name | Code | Data Type | Length |
日期代理键 | DATE_PK | INTEGER | |
日期描述 | DATE_DESC | VARCHAR2(8) | 8 |
日期长描述 | DATE_LDESC | VARCHAR2(20) | 20 |
日期中文描述 | DATE_CNDESC | VARCHAR2(20) | 20 |
天 | DAY | NUMBER | |
天中文 | DAYCN | VARCHAR2(10) | 10 |
月 | MONTH | NUMBER | |
月中文 | MONTH_DESC | VARCHAR2(10) | 10 |
年 | YEAR | NUMBER | |
年中文 | YEAR_DESC | VARCHAR2(10) | 10 |
年月 | YEARM_ONTH | VARCHAR2(6) | 6 |
周月 | WEEKMONTH | NUMBER | |
周月中文描述 | WEEK_MONTH_CNDESC | VARCHAR2(20) | 20 |
年中第几周 | WEEK_YEAR | NUMBER | |
年中第几周描述 | WEEK_YEAR_CN | VARCHAR2(20) | 20 |
周几 | WEEKNO | NUMBER | |
周几中文描述 | WEEK_CN | VARCHAR2(10) | 10 |
旬 | XUN | NUMBER | |
旬中文 | XUNCN | VARCHAR2(10) | 10 |
季度 | QUARTER | NUMBER | |
季度中文 | QUAR_CN | VARCHAR2(10) | 10 |
是否周末 | IF_WEEKEND | VARCHAR2(10) | 10 |
是否月末 | IF_MONTHEND | VARCHAR2(10) | 10 |
节假日名称 | HOLIDAY | VARCHAR2(10) | 10 |
上月同一天 | LASTMONTH_DAY | VARCHAR2(8) | 8 |
去年同一天 | LASTYEAR_DAY | VARCHAR2(8) | 8 |
3.2. 层级维度
层级维度也是我们模型设计最常遇见的维度,比如组织结构,区域,产品树,行业结构等等。在设计时,可以采用如下模板:
针对数据存储时,采用自关联的结构:
Name | Code | Data Type | Length |
组织代码 | ORG_CODE | VARCHAR2(20) | 20 |
上级组织代码 | PORG_CODE | VARCHAR2(20) | 20 |
组织名称 | ORG_NAME | VARCHAR2(100) | 100 |
上级组织名称 | PORG_NAME | VARCHAR2(100) | 100 |
组织类型 | ORG_TYPE | VARCHAR2(20) | 20 |
组织层级 | ORG_LEVEL | VARCHAR2(20) | 20 |
组织描述 | ORG_DESC | VARCHAR2(200) | 200 |
组织简称 | ORG_SNAME | VARCHAR2(20) | 20 |
组织地址 | ORG_ADDR | VARCHAR2(100) | 100 |
针对数据展现时,将自关联的结构展开,以列存储层次:
根据需要可以把组织层级具体化。
Name | Code | Data Type | Length |
组织代理键 | ORG_KEY | INTEGER | |
组织代码 | ORG_CODE | VARCHAR2(30) | 30 |
组织名称 | ORG_NAME | VARCHAR2(50) | 50 |
组织描述 | ORG_DESC | VARCHAR2(100) | 100 |
组织简称 | ORG_SNAME | VARCHAR2(50) | 50 |
组织层级 | ORG_LEVEL | VARCHAR2(30) | 30 |
组织类型 | ORG_TYPE | VARCHAR2(20) | 20 |
上级组织代码 | ORG_PCODE | VARCHAR2(30) | 30 |
上级组织名称 | ORG_PNAME | VARCHAR2(50) | 50 |
组织1级代码 | ORG_1_CODE | VARCHAR2(50) | 50 |
组织1级名称 | ORG_1_NAME | VARCHAR2(50) | 50 |
组织2级代码 | ORG_2_CODE | VARCHAR2(50) | 50 |
组织2级名称 | ORG_2_NAME | VARCHAR2(50) | 50 |
组织3级代码 | ORG_3_CODE | VARCHAR2(50) | 50 |
组织3级名称 | ORG_3_NAME | VARCHAR2(50) | 50 |
组织4级代码 | ORG_4_CODE | VARCHAR2(50) | 50 |
组织4级名称 | ORG_4_NAME | VARCHAR2(50) | 50 |
组织5级代码 | ORG_5_CODE | VARCHAR2(50) | 50 |
组织5级名称 | ORG_5_NAME | VARCHAR2(50) | 50 |
组织6级代码 | ORG_6_CODE | VARCHAR2(50) | 50 |
组织6级名称 | ORG_6_NAME | VARCHAR2(50) | 50 |
组织7级代码 | ORG_7_CODE | VARCHAR2(50) | 50 |
组织7级名称 | ORG_7_NAME | VARCHAR2(50) | 50 |
组织8级代码 | ORG_8_CODE | VARCHAR2(50) | 50 |
组织8级名称 | ORG_8_NAME | VARCHAR2(50) | 50 |
代理键开始时间 | KEY_STARTDATE | VARCHAR2(30) | 30 |
代理键结束时间 | KEY_ENDDATE | VARCHAR2(30) | 30 |
有效标志 | CURRENT_FLAG | INTEGER | |
修改时间 | KEY_MODIFYDATE | VARCHAR2(30) | 30 |
3.3. 缓慢变化维
缓慢变化维定义
数据会发生缓慢变化的维度就叫”缓慢变化维”。
举个例子就清楚了:
在一个零售业数据仓库中,事实表保存着各销售人员的销售记录,某天一个销售人员从北京分公司调到上海分公司了,那么如何来保存这个变化呢?也就是说销售人员维度要怎么恰当的处理这一变化。先来回答一个问题,为什么要处理,或保存这一变化?如果我们要统计北京地区或上海地区的总销售情况的时候,这个销售人员的销售记录应该算在北京还是算在上海?当然是调离前的算在北京,调离后的算在上海,但是如标记这个销售人员所属区域?这里就需要处理一下这个维度的数据,即我们缓慢变化维需要做的事情。
处理缓慢变化维一般按不同情况有以下几种解决方案:
3.3.1. 新数据覆盖旧数据
此方法必须有前提条件,即你不关心这个数剧的变化。例如,某个销售人员的英文名改了,如果你不关心员工的英文名有什么变化则可直接覆盖(修改)数据仓库中的数据。
3.3.2. 保存多条记录,并添加字段加以区分
这种情况下直接新添一条记录,同时保留原有记录,并用单独的专用的字段保存区别。如:
(以下表格中Supplier_State表示上面例子中所属区域,为描述清晰,不用代理键表示)
Supplier_key | Supplier_Code | Supplier_Name | Supplier_State | Disable |
001 | ABC | Phlogistical Supply Company | CA | Y |
002 | ABC | Phlogistical Supply Company | IL | N |
或:
Supplier_key | Supplier_Code | Supplier_Name | Supplier_State | Version |
001 | ABC | Phlogistical Supply Company | CA | 0 |
002 | ABC | Phlogistical Supply Company | IL | 1 |
以上两种是添加数据版本信息或是否可用来标识新旧数据。
下面一种则是添加记录的生效日期和失效日期来标识新旧数据:
Supplier_key | Supplier_Code | Supplier_Name | Supplier_State | Start_Date | End_Date |
001 | ABC | Phlogistical Supply Company | CA | 01-Jan-2000 | 21-Dec-2004 |
002 | ABC | Phlogistical Supply Company | IL | 22-Dec-2004 |
空的End_Date表示当前版本数据,或者你也可一用一个默认的大时间 (如: 12/31/9999)来代替空值, 这样数据还能被索引识别到.
3.3.3. 不同字段保存不同值
Supplier_key | Supplier_Name | Original_Supplier_State | Effective_Date | Current_Supplier_State |
001 | Phlogistical Supply Company | CA | 22-Dec-2004 | IL |
这种方法用不同的字段保存变化痕迹.但是这种方法不能象第二种方法一样保存所有变化记录,它只能保存两次变化记录.适用于变化不超过两次的维度。
3.3.4. 另外建表保存历史记录
即另外建一个历史表来表存变化的历史记录,而维度只保存当前数据。
Supplier:
Supplier_key | Supplier_Name | Supplier_State |
001 | Phlogistical Supply Company | IL |
Supplier_History:
Supplier_key | Supplier_Name | Supplier_State | Create_Date |
001 | Phlogistical Supply Company | CA | 22-Dec-2004 |
这种方法仅仅记录一下变化历史痕迹,其实做起统计运算来还是不方便的。
3.3.5. 混合模式
这种模式是以上几种模式的混合体,相对而言此种方法更全面,更能应对错综复杂且易变化的用户需求,也是较为常用的。
Row_Key | Supplier_key | Supplier_Code | Supplier_Name | Supplier_State | Start_Date | End_Date | Current Indicator |
1 | 001 | ABC001 | Phlogistical Supply Company | CA | 22-Dec-2004 | 15-Jan-2007 | N |
2 | 001 | ABC001 | Phlogistical Supply Company | IL | 15-Jan-2007 | 1-Jan-2099 | Y |
此中方法有以下几条优点:
能用简单的过滤条件选出维度当前的值。
能较容易的关联出历史任意一时刻事实数据的值。
如果事实表中有一些时间字段(如:Order Date, Shipping Date, Confirmation Date),那么我们很容易选择哪一条维度数据进行关联分析。
其中Row_Key和 Current Indicator字段是可有可无的,加上去更方便,毕竟维度表的数据都不大,多点冗余字段不占太大空间但能提高查询效率。
这种设计模式下事实表应以Supplier_key为外键,虽然这个字段不能唯一标识一条维度数据,从而形成了事实表与维表多对多的关系,因此在做事实和维度做关联时应加上时间戳字段(或Indicator字段)。
3.3.6. 非常规混合模式
上面说到第五种实现方式有点弊端,那就是事实表和维表不是多对一关系,而是多对多关系,这种关系不能在建模时解决只能在报表层面,在报表运行时解决,且在BI语意层建模时需要添加时间过滤条件,比较繁琐。
下面这种解决方案可以解决此多对多关系,但是得修改一下事实表:
Supplier Dimension:
Version_Number | Supplier_key | Supplier_Code | Supplier_Name | Supplier_State | Start_Date | End_Date |
1 | 001 | ABC001 | Phlogistical Supply Company | CA | 22-Dec-2004 | 15-Jan-2007 |
0 | 001 | ABC001 | Phlogistical Supply Company | IL | 15-Jan-2007 | 1-Jan-2099 |
Fact Delivery: (为描述清晰,同样不使用代理键标识维度)
Delivery_Key | Supplier_key | Supplier_version_number | Quantity | Product | Delivery_Date | Order_Date |
1 | 001 | 0 | 132 | Bags | 22-Dec-2006 | 15-Oct-2006 |
2 | 001 | 0 | 324 | Chairs | 15-Jan-2007 | 1-Jan-2007 |
此方案中向维表中的当前数据版本号始终为0,即插入维度数据时先将老版本的数据的version_number改成1(递增),然后再插入当前数据,此时才能保持当前数据版本号始终为0。
事实表中插入数据时所有的维度数据版本号始终全部为0。
因此此方案完全可解决事实表和维表多对多关系问题,另外还有个优点是能保证事实表和维表的参照完整性,而且我们在用ERwin,PowerDesigner等建模工具建模时,Version_Number和Supplier_key可作为复合主键在两实体间建立链接。
4. 事实表设计
事实表中一般要包含2部分:一是由主键和外键所组成的键部分,另一部分是用户希望在数据仓库中所了解的数值指标,这些指标是为每个派生出来的键而定义和计算的,称为事实或指标。由于事实是一种度量,所以事实表中的这种指标往往需要具有数值化和可加性的特征。但是在事实表中,只有那些具有完全可加性的事实才能根据所有的维度进行累加而具有意义。而事实表有一些事实表示的是某种强度,这类事实就不具有完全加法性,而是一种半加法性。例如,账目余款反映的是某个时间点的数据,它可以按照地点和商品等大多数维度进行累加,但是对于时间维度则例外,将一年中每个月的账目余款进行累加是毫无意义的,而决策者则可能需要了解所有地区和所有商品账目余款的累加值。在事实表中还有一些事实是非加法性的,即这些事实具有对事实的描述特性,在这种情况下一般要将这些非加法性事实转移到维度表中
4.1. 事务事实表
大多数基本事实表和公共事实表都是面向事务的,其粒度是每一行对应个一事务,或者一行对应事务中的一个条目。事务粒度是空间和时间的交点,一个事务粒度上的度量必须在那个时刻为真。
事务数据在其最低层次上一般都有数目巨大的维与之相关联。无论事务事件何时出现,都可以捕捉到有关事务的大量上下文,仅当活动发生时,事务事实表中才会插入一行。一旦事务事实行已经存储,一般不会再次对其进行访问。
如下面的业务过程,就非常适合用事务事实表来表示:
l 采购
l 下订单
l 缴费
l 支付
l 购买
l 拨打电话
4.2. 快照事实表
第二种最常见的事实表类型是周期快照。使用周期快照可以得到一组描述,周期快照能够按照一个定义良好的时间周期间隔来捕捉业务过程的执行情况,并且将这些描述装载到事实表中。在预定义好的间隔(如每天、每周或者每月)上,很多描述都是关于相同细节层次的,它们连续不断地进入事实表。
如下面的业务过程,就非常适合用快照事实表来表示:
l 银行账户的余额
l 财务月报表
5. 数据库设计规范
5.1. 数据库表设计规范
数据库对象 | 前缀 | 命名说明 |
表 | 层次_模块名_具体功能实体名, 如产品维表L0_DIM_PRODUCT等, 附注:在公司模型产品中,我们规定分如下层次 L0 》L1 》L2 | |
维表 | DIM | 层次_模块名_具体功能实体名, 如产品维表L0_DIM_PRODUCT等, |
事实表 | FACT | 层次_模块名_具体功能实体名, 如销售事实表L1_FACT_SALE等, |
列名 | 参见附件中常见属性命名规范 | |
代理键 | KEY | 如日期代理键 DATE_KEY |
存储过程 | SP_ | 前缀_层次_主题_功能 如:SP_L2_CUSTOMER_YTD |
视图 | VW_ | VW_层次_直接的内容, 一般是用于查询Query和报表Report两种情形 |
触发器 | TRG_ | 方法一: TRG_表名_方法名_[之前之后等] 比如: TRG_USER_INFO_INSERT |
函数 | FN_ | FN_功能名称。 |
主键 | PK_ | PK_表名[或缩写]_列名 简洁的写法: 写法一:PK_表名, 写法二:PK_列名,因为列名设计时已经包含表的含义 |
外键 | FK_ | FK_从表名字段_主表名字段。这个推荐 |
索引 | IDX_ | IDX_表名_字段名(一个或多个)【可以在其后加U或者C,规则同触犯器】 推荐使用:IDX_字段名 一是唯一Unique【U】与非唯一NonUnique【N】 一是聚集Cluster【C】与非聚集NonCluster【N】 |
约束 | CK_ | 1. 默认约束:DF_表名_列名,DF_列名 |
2.唯一约束:UNI_表名_列名,UNI_列名 | ||
3.检查约束:【CK_列名】,【CK_表名_列名】 | ||
4.主键约束:【PK_表名】,【PK_列名】 | ||
5.外键约束:fk_表名_REFERENCE_表名 | ||
序列 | SEQ_ | 写法1:SEQ_USER_INFO(因为每个表一般只有一个序列) 写法2:SEQ_UI_ID (因为表名含义已经包含在字段中) 写法3:SEQ_USER_INFO_UI_ID(表名加字段名) |
事务 | TRANS_ | trans_ |
游标 | CRS_ | CRS_ |
表空间 | _DATA _IDX _TMP _RBS | @面向用户或者应用名,这个以用户名或者应用名加后缀组成 数据表空间以用户名+_+DATA命名 索引表空间以用户名+_+IDX命名 专用临时表空间以用户名+_+TMP命名 专用回滚段表空间以用户名+_+RBS 命名 特殊处理: |
5.2. 数据库索引设计规范
5.2.1. 维度表索引设计
维度表应当有单独的一列作为主键,这样就可以在该主键上建立唯一索引。如果数据库管理系统支持位图索引(我们一般选用ORACLE),可以为哪些常用作筛选条件的维度属性每列添加一个位图索引。如果数据库管理系统部不支持位图索引,可以创建B-tree索引。
在比较小的维度表上不建议创建联合索引,但在比较大的维度表上,比如客户维度表上,经常有各种各样的查询,比如客户群细分等不涉及事实表的查询需求。可以建立联合索引。
5.2.2. 事实表索引设计
事实表逻辑主键的一般是维度表主键的外键联合。所以,在每一个外键上,我们都建议建立位图索引,这样在事实表比较巨大的情况下,可以使索引变得非常小,可以大大节省磁盘空间,更重要的是,这些索引可以全部放到内存里面,从而给查询速度带来很大提高。
5.2.3. 装载后分析表和索引
有些数据库引擎在每次装载过程完成之后不会对表和索引自动进行统计和重新计算,有些甚至在重建一个完整的索引之后也不会进行验算。这对任何装载和索引创建过程都是非常重要的步骤。因为查询优化器必须拥有关于表和索引大小的准确信息,以便设计出高效的查询方案。
如在oracle中,我们可以用如下语句进行表和索引的分析。
Analyze table table_name compute statistics .
6. 常见表命名规范
表名 | 全称 | 类型 |
日期维度表 | DW_DIM_DATE | 维度表 |
月份维度表 | DW_DIM_MONTH | 维度表 |
组织维度表 | DW_DIM_ORG | 维度表 |
客户维度表 | DW_DIM_CUST | 维度表 |
产品维度表 | DW_DIM_PRODUCT | 维度表 |
指标维度表 | DW_DIM_KPI | 维度表 |
银行维度表 | DW_DIM_BANK | 维度表 |
员工维度表 | DW_DIM_EMPLOYEE | 维度表 |
区域维度表 | DW_DIM_AREA | 维度表 |
部门维度表 | DW_DIM_DEPT | 维度表 |
行业维度表 | DW_DIM_INDUSTRY | 维度表 |
渠道维度表 | DW_DIM_CHANNEL | 维度表 |