2010-07-29
摘要
面向对象(OO)和三范式(3NF)都是成熟的设计方法,本文基于面向对象设计思想和三范式数据库设计方法,提出一种实体对象分层建模的思路,其目的是设计简单明了、标准化的数据库结构,同时能够更好的支持模型驱动模型(MDA)的代码自动生成和代码复用,减少代码编写工作量。
面向对象的数据库设计
本模型探讨的一个数据库建模的方法,其意义主要是为《面向服务体系架构(SOA)和数据仓库(DW)的思考》(以下简称《SOA和DW》)所述的共享库提供方法论支持,建立一个简单明了、易于理解的标准化的数据结构,共享库的主要目的是为了共享数据,需要建立一个简单明了,标准化的数据结构。同时为基于模型驱动(Model Driven Architecture,MDA)的设计方法提供一个简化的数据结构,更加容易根据数据结构自动生成代码。
本文采用InfoSphere Data Architect作为工具支持,主要针对需要持久化的业务对象(Business Object,BO))进行实体对象(Entity Object 或者称持久化对象 Persistant Object,PO)的逻辑数据模型 (Logical Data Model)设计。本文中业务对象设计不再详细论述,假设是已经做了业务对象分析,然后基于业务对象模型生成实体对象模型,并根据实体对象分层模型进一步完善业务对象模型。
面向对象方法(Object-Oriented Method,OO方法)是一种把面向对象的思想应用于软件开发过程中,指导开发活动的系统方法,是建立在“对象”概念基础上的方法学。面向对象包含面向对象的分析(Object Oriented Analysis,OOA),面向对象的设计(Object Oriented Design,OOD)、面向对象的编程实现(Object Oriented Programming,OOP)等,面向对象的分析(OOA)方法是本模型的基本方法。面向对象的方法,当前有成熟的基于UML(Unified Modeling Language)建模方法论,本文不再详述。
第一范式(1NF)无重复的列,实体中的属性不能有多个值或者不能有重复的属性。第二范式(2NF)要求数据库表中的每个实例或行必须可以被唯一地区分,不能存在仅依赖主关键字一部分的属性。 第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。在本模型中,如果出现重复的属性,就需要增加一个实体对象,并根据新增对象和原对象的主键关系确定其对象关系。从性能角度考虑,在数据表中增加了冗余外键对应关系,即并非完全满足3NF的要求。
维度建模(Dimensional Modeling,DM)是数据仓库建设中的一种数据建模方法。按照事实表,维表来构建数据仓库,数据集市。在本模型中,对象汇总关系部分采用了维度建模的思想,但是没有深入的探讨维度建模方法论,关于维度建模可以参考相关的资料。
模型驱动架构(MDA)
模型驱动架构(Model Driven Architecture,MDA)是由OMG定义的一个软件开发框架。它是一种基于UML以及其他工业标准的框架,支持软件设计和模型的可视化、存储和交换。和UML相比,MDA能够创建出机器可读和高度抽象的模型,这些模型独立于实现技术,以标准化的方式储存。本模型的第二个目标就是为建立更高效率的自动生成代码提供一个数据基础。。
IBM InfoSphere Data Architect(以下简称IDA) 是一种协作式的数据设计解决方案,能用于发现、建模、关联和标准化各异的分布式数据资产。如图1所示,是实体对象分层模型最终完成之后的界面,IDA能够很好的支持分层的建模,可以到IBM网站下载IDA试用版。
图 1 InfoSphere Data Architect界面
示例模型说明
为了更好的描述对象模型,将以销售管理系统为例进行介绍,包含系统管理和销售管理两个部分,销售管理主要实现货物的采购和销售管理,包含组织机构、人员、仓库、商品批号、供应商、客户;销售订单、采购订单、出入库单等业务单据。其整体模型如图2所示:
图 2 本文示例主要对象关系图
以下以面向对象设计为基础,按照三范式建模方式,采用IDA 7工具,从最简单的实体对象对象模型入手,逐步细化模型,其基本框架模型下找出所有对象之间的关系,并模式化。
对象关系模型
业务对象(BO)包含复杂的逻辑关系,通过对业务对象及实体对象之间的关系的分析,将对象的关系简化为对象基本关系、对象变更关系、对象汇总关系、类别对象关系等,针对对象数据不确定的对象,建立属性不确定对象关系。除了对象之间的关系外,本模型增加了一个附加对象层,包含树装结构、时间结构等,用于处理一个特殊的业务需求。
在本模型中,实体对象基本关系是核心,确定了基本关系,也就把数据库的整体框架搭建起来了,其他模型可以看作仅仅是一个范式,在设计数据库的时候选择一个范式即可。本文虽然是以实体对象进行建模,但是其和业务对象是对应的,所以其关系模型也适应于业务对象。
根据实体对象之间的关系,将实体对象分成标准元实体对象、元实体对象和关联实体对象三类。这三类实体对象构成了实体对象关系的基本框架。如图3所示:
图 3 对象基本关系图
- 标准元实体对象:实体对象完全独立,不依赖于任何其他的实体对象,典型标准元实体对象如组织机构、国家等内容。标准元实体对象完全独立,有标准的编码体系(一般都有企业标准、国标或者国际标准),不会因为在不同的系统不同有不同编码体系。标准元实体对象只有一个主键。
- 元实体对象:独立的实体对象,和标准元实体对象不同,一般没有一个唯一的标识符,需要增加一个唯一标识符(比如单位编码,需要制定一个编码规则,主要目的在于未来数据合并的时候不会因为多个系统合并而使得数据重复),然后才能唯一标示对象。元实体对象是建模中最基本、最核心的对象。如客户,订单、流程等,是业务逻辑、对外接口的核心实体对象。标准元实体对象是有标准编码体系特殊的元实体对象。
- 关联实体对象:标准元实体对象、元实体对象之间的关联对象,有些仅仅是简单的关联,有些关联对象中含有其他的业务信息。前者仅仅是对应关系,后者包含对应关系的其他属性。如具体一个公司的商品价格信息,是实体对象-商品和组织机构关联之后的信息。关联对象本身也是一个特殊的实体对象。关联实体对象主键一般是两个或者两个以上,一般来说,应该尽量减少关联对象的主键数量。
- 根据实体对象(含元实体对象和关联实体对象)数量增长的快慢,可以把实体对象分成基础实体对象和流水实体对象,前者实体对象一般变化缓慢,如客户数据(比较重要的基础元实体对象一般对应着的是主数据),后者变化快,如订单数据等。
除了以上基本关系之外,还有一些特殊的实体对象关系,包含附属关联实体对象、主从关联实体对象等
- 附属关联实体对象:实体对象的附属信息,和实体对象是一对一或者一对多关系。一对一关系一般是为了把一个属性太多的对象分解成多个(在IDA中可以用继承来描述);一对多关系采用增加序号的方式,增加多条信息。如人员的学历、工作经历等。不同于关联对象,其只是简单的序号的增加。订单可以以客户编码和流水号作为主键,但是这种有流水号主键的一般是可以将几个主键合并为一个主键,如果能合并为一个主键,则合并为一个主键,从而简化模型的层次。附属关系一般是为了解决简单一对多的附属信息,如果附属对象需要复杂的业务逻辑,需要将多个主键合并为一个主键。
- 主从关联实体对象:关联实体对象的一种特殊情况,关联的两个对象之间有强烈的主从关系,如订单和订单项等。主从管理实体对象一般从对象内容有限,在软件实现中一般以单据方式进行展示。
除了基本的关联关系之外,对象和对象之间还有外键关系,外键关系不象关联关系那样是主键关系,外键关系是外键关联。如图4所示:
图 4 对象外键关系图
在本模型中,比较一个关键的一点是要尽量多的建立元实体对象,特别是标准元实体对象,尽量减少关联实体对象。比如订单,是元实体对象不是关联实体对象,即客户和订单的关系不是主键关系而是外键关系。外键有多种,如一对一、一对多关系等,详见IDA中的设置。一个简单的原则可以来判断,如果关联实体对象除了关联的实体对象的主键之外还需要一个独立的主键,就应该考虑看作是一个元实体对象(附属关联实体对象、主从关联实体对象除外,其特点是多加出来的一个主键仅仅是一个序号,如果也做为一个元实体对象,将会导致对象模型过于复杂)。
对象基本关系模型构成了对象关系模型的主要框架,除此之外,还有一些其他的关系模型,包括对象变更模型、对象汇总模型、类别对象关系模型、附加对象关系模型、不定属性对象关系模型。对于设计者来说,需要关注的仅仅是基本关系模型,其他模型的设计可以看作是固化了的设计范式,只需要设定范式即可。
实体对象实例在业务活动过程中不断发生变化,根据业务的需要,需要记录实体对象实例的变化信息(不同于流水元实体对象,是多个对象实例,比如订单,随着业务的变化,订单不断增加)。包括对象属性变更、对象整体变更、对象快照等。另外从业务上考虑,为了实现操作痕迹化,需要对操作过程进行记录。如图5所示
图 5 对象变更关系图
- 实体对象属性变更,对属性变化的历史进行记录。根据记录的先后顺序可以分成两种:采用申请单的方式,先记录变化的信息,然后更改实体对象;监控对象变化,变化之后记录变化之后的属性。对于不重要的属性可以选择不记录变更情况。
- 实体对象整体变更,对实体对象的变更情况整体记录,记录更改后的完整信息,一般适合于流水元实体对象,用于记录流水对象的变化情况。
- 实体对象快照,为了便于记录历史信息,可以完整的还原当时的场景,记录当时所有实体对象的信息,作为实体对象的快照进行管理。快照不同于后文所述的汇总表,快照仅仅是对原始对象的原样备份,汇总表则是实现对内容“汇总”之后的记录。
- 实体对象操作痕迹化管理,对于一些关键业务数据,业务上需要保留操作痕迹,比如订单数量修改和删除需要记录相应的信息。采用两种方式来解决,一个是不允许删除实体对象,只做实体对象除删除标记,适用于整条记录删除的情况;对于记录变更的情况,采用增加一个废弃实体对象,记录实体对象的修改记录。
实体对象发生连续变化之后,需要对变化信息的汇总成为汇总对象,包含汇总和计数,和实体对象的关系为对象汇总关系,包括按照年、月、日、周、季等汇总,分别形成年、月、日、周、季的汇总表。根据汇总对象和原始对象之间的关系,可以分成简单汇总关系和分组汇总关系,后者根据原始对象的外键关系进行分组汇总。分组汇总关系又可以分成历史分组汇总和当前分组汇总。汇总对象属性可能来源于多个原始实体对象,为了统一模式可以先分别汇总,然后再进行合并。如图6所示:
图 6对象汇总关系图
- 简单汇总关系,直接基于原始对象按照时间进行汇总。
- 分组汇总关系,基于原始对象的外键关系进行分组汇总,比如客户渠道、客户组织机构等,根据外键对象是否变化可以分成历史分组汇总和当前分组汇总。前者按照原始实体对象历史上的状态进行汇总,当前分组汇总根据当前的分类情况进行汇总,其数据是动态的,需要根据最新的分组汇总情况进行重新汇总。
由于汇总对象是对应的实体对象的按照年、月、日的汇总,因此其主键为原实体对象加年ID、月ID或日ID。是和日期对象的一种特殊的关联实体对象。
汇总对象更多的承担着报表查询的功能,为了提高查询性能,可以在汇总对象增加额外的外键对应关系甚至把属性进行冗余存储。(汇总对象建模需要参考星形建模,详见关于数据仓库建模)
为了减少存储空间和便于统计,将主实体对象(包含元实体对象和关联实体对象)的属性进行分类管理,以编码替代文字描述,成为类别对象,类别对象和主实体对象的关系式外键关联关系。如图7所示:
图 7类别对象关系图
- 类别对象:实体对象的属性描述信息,和元对象的差别是,类别对象仅仅是一个标识和描述,没有具体的业务属性信息,一般不作为主键。根据类别对象是否独立可以将类别对象分成独立类别对象和依附类别对象,前者跟其他的实体对象没有任何关系,后者需要根据关联的实体对象确定对应关系。
- 合并的类别对象:对于简单的属性,可以汇总为一个对象,通过分类进行管理,如图8所示:
图 8类别对象合并存储
由于是对象合并的,所以合并之后的对象需要增加一个主键,作为标识。需要注意的是对象基本关系模型中涉及的标准元实体对象、元实体对象和关联实体对象,除了前两者有一个独立的主键之外,关联实体对象,除了附属关联实体对象外一般都是对应着一组关联对象的主键,关联对象一般没有自己的主键(附属关联对象比较特殊)
附加对象一般不是一个独立的对象,需要附加于其他对象,但是其具有本身的一些特点,包含树、图、修改日志【时间戳】、数据校验位等附加对象。如图9所示:
图 9树附加对象关系图
树附加对象,根据实体对象是否可以有多个树,可以将树附加对象分成独立树对象和内嵌树附加对象
- 独立树对象可以有多个树,即一个实体对象可以出现在不同的独立树对象中。根据实体对象在一个独立树对象中是否可以重复,可以把独立树对象分成唯一独立树对象和复合独立树对象两种。唯一独立树对象中的实体对象在树中式唯一的,复合独立树对象的实体对象在树对象中式可以重复出现的,如上图中的定制菜单,同一个菜单可以出现在不同的菜单目录中。
- 内嵌树只有一个树附加对象,树附加对象和实体对象是一一对应的,因此一般来说,内嵌树附加对象和实体对象可以合并为为一个对象。
- 网附加对象是一种特殊的树附加对象,其特点是父对象不是一个,而是两个。网对象根据树附加对象的划分相对应,也可以分成三种。
- 操作痕迹化记录:每个对象包含:创建时间、创建者、修改时间、修改者。所有的表都可以附加上,作为表结构的一个部分。
- 对象标识符ID,系统自动生成,作为对象的唯一标示,可以自动生成,数据迁移之后,其数值会发生变化,不可以作为主键。
由于有些对象的属性是不确定的,可以动态增加或者所有对象的属性很多,但是具体到一个对象,其属性有只是很少的几个,属于不定属性对象,为了进行持久化,将对象的属性按照行进行存放。如图10所示:
图 10不定属性对象关系图
不定属性实体对象属性多变,没有固定的属性,需要灵活处理每个对象的属性,典型的如考核指标,不同的部门、不同的公司指标的差异非常大,因此需要按照每个指标的类别,在行上进行存储。一般来说,指标本身是一种树,指标本身有关联。
不定属性对象其特点和一般的实体对象一样,其特殊之处在于其属性是变化的,对象实例化的时候,对象是存储是在行上存储的。
如果属性数量是明确的,但是不同类别实体对象具有的属性不同,可以通过继承或者关联关系建立附属关联关系。比如商品信息,分别建立消费品商品信息、电器商品信息等,用与分别记录其不同的信息。
如果属性相对来说是稳定的,但是存在变化的可能,则需要考虑实体对象属性动态增加的模式。比如工资条,存在着工资条内容的增减,因此需要特殊考虑。
本模型以面向对象的分析为基本方法,首先找出业务对象(BO),然后基于范式理论把业务对象转化成实体对象(PO),并进行分类分层管理,根据主键的特点,设置实体对象的基本层级,最终建立实体对象分层模型。
实体对象关系模型应用
在《SOA和DW》中提到了关于共享库的概念,共享库是为所有厂商提供一个标准数据来源的共享库,是企业级的数据库,由多个厂家共同建设和使用,包含元数据、主数据、用户数据、业务数据等,因此需要共享库数据结构清晰明确,并建立统一的建模标准,因此可以采用本模型进行数据库建设,建立企业级的清晰、规范的数据库模型。《表 1 按照分层模型对数据库表进行分类》。
表 1 按照分层模型对数据库表进行分类
模型 | 对象关系 | 备注 |
对象基本关系模型 | 标准元实体对象 | 标准元实体对象一般对应着主数据,特别是在多个系统共同使用的数据,为主数据。 |
元实体对象 | 业务系统的核心实体对象,包含基础元实体对象和流水元实体对象两种 | |
关联实体对象 | 基于元实体对象的关联关系 | |
附属关联实体对象 | 特殊的关联实体对象 | |
主从关联实体对象 | 特殊的关联实体对象 | |
对象变更关系 | 实体对象属性变更 | 仅记录某个属性变化信息 |
实体对象整体变更 | 记录对象整体变化信息 | |
实体对象快照 | 记录所有对象的当时信息 | |
实体对象操作痕迹化管理 | 记录操作者对实体对象的变更信息 | |
对象汇总模型 | 简单汇总关系 | 包含日、月、年、周、季等,原始对象的简单汇总 |
历史分组汇总 | 原始对象的分组汇总,记录当时历史状况,记录是不可以修改的 | |
当前分组汇总 | 按照当前分类情况,重新的汇总 | |
类别对象关系模型 | 全局类别对象 | 整个系统全部统一 |
附属类别对象 | 隶属于元实体对象的类别,不同的元实体对象类别不同 | |
合并的类别对象 | 对于简单的分类编码,可以汇总为一个实体对象,统一管理所有的分类实体对象 | |
附加对象关系模型 | 唯一独立树对象 | 可以有多个树,树的节点实体对象不可以重复 |
复合独立树对象 | 可以有多个树,树的节点实体对象可以重复 | |
内嵌树附加对象 | 实体对象和树附加对象一一对应 | |
网对象 | 特殊的一种树附加对象,树节点的父节点可以有多个 | |
其他附加对象属性 | ID、操作痕迹化记录等 | |
不定属性对象关系模型 | 包含以上所有对象关系 | 和前面对象的差异在于其属性由列存储变为行存储 |
采用本模型,设计者需要关注的仅仅是对象基本关系,即元实体对象和关联实体对象,如《表 2 描述对象关系的表格》所描述,从而简化了数据结构,统一了数据库设计风格。
表 2 描述对象关系的表格
元实体对象 | 关联实体对象 | 外键关系 | 其他(汇总、变更、附属、不定属性等) |
(包含是否标准实体对象信息) | (关联的元实体对象以及关联类别) | (包含实体对象、类别对象) | |
XX元实体对象 | XXX关联实体对象 | XXX实体对象 | |
XXXXX实体对象 | |||
YY元实体对象 | YY关联实体对象 | YYY实体对象 | |
YYYY实体对象 |
对象基本关系模型确定之后,其他关系可以通过设定已有的模型自动生成,只需要在设计的时候设定其他模型类别即可,比如根据实体对象的变更记录设置,自动生成变更表;根据设定的对象汇总关系可以自动生成汇总表;根据类别对象关系,自动对应类别对象;根据设定的附加对象自动生成树等结构;根据不定属性对象关系自动生成不定属性表等。相关信息可以参考元对象设施(Meta-Object Facility,MOF)的概念,即可以实现MOF的M1层模式化设计,本文不再详细探讨。
模型在模型驱动架构(MDA)中的应用
实体对象按照分层模型建立之后,在IDA中设置词汇表(Glossary),IDA可以自动生成各种主流数据库的数据结构,同时分层模型建立了实体对象之间的关系,根据实体对象分层模型,进一步完善业务对象(BO)模型,可以设置更多的自动生成代码模板,提高代码生成效率。比如:
- 主从表关系,可以自动生成所有单据类的代码。
- 关联实体对象,自动生成对象关联的维护;根据外键关系可以自动生成:简单列表方式选择;外键的外键,简单树型显示;外键+外键,笛卡尔积的树显示。
- 类别对象关系,特殊的外键关系,可以自动生成弹出或者下拉窗口,在数据查询的时候可以自动根据代码转换成文字描述;
- 对象汇总关系,自动生成汇总程序,需要标记属性的类别,比如汇总还是计数。
- 对象变更关系,自动生成变更程序以及变更跟踪等。
- 附加对象关系,比如根据树的类别,自动生成树的维护程序。
- 不定属性关系,可以自动实现行列转换等的计算等。
基本的数据操作层面的代码可以全部自动生成,如简单的增删改查、以自动完成删除订单,然后自动删除订单项等关联关系。关于更多的MDA的实现,将在本文的续篇进一步探讨。
总结
本文以面向对象设计方法和三范式为基础,提出了分层的实体对象模型,建立了一个标准化的数据库关系模型。遵循这个标准,可以建立更加清晰易懂的数据结构,为建立企业级的共享库打下基础,同时本模型能为更有效的自动生成代码提供基础。
本模型的适用范围和不足:
本模型仅限应用在数据库管理软件中,是面向数据库操作的实体对象建模模型。
本模型仅限解决实体对象之间的关系,如果要实现完整的代码自动生成,还需要界面层的设计模型,复杂业务逻辑和业务规则则需要相关的软件支持。
本模型无法解决复杂数据处理逻辑的和数据查询方面的课题。
基于面向对象(OO)的数据库设计模式探讨2
关于面向对象和面向数据
虽然面向对象是更多的从编码角度考虑,但对于基于数据库的管理系统来讲,数据时核心,因此,笔者从第一篇文章开始,宏观上就是讲述数据的架构,微观角度,也是从数据角度出发,这是程序的设计基础。当然,数据本身也是从面向对象开始的。因此其思路遵循面向对象的对象设计,数据结构设计,面向对象的业务逻辑设计,并进一步完数据结构设计。
现在大型的管理系统有几千甚至上万张表,但几乎没有谁能搞清楚所有的数据结构,如何建立清晰明了的数据结构?如何让其他人对数据结构更加容易理解,本文以《基于面向对象(OO)的数据库设计模式探讨》为基础进一步对汇总表进行分析,通过建立指标矩阵模型,“模式”化数据库建模,建立清晰可读的汇总数据模型。
前言
在软件开发过程中,几乎没有几个程序员喜欢报表开发,报表多、杂,需求多变,特别是给人感觉没有什么技术含量,大家对报表都是退避三舍。如果采用BI工具开发,又会因为BI工具五花八门,不同项目BI工具不同,需要开发不同的程序,增加了项目开发成本,除非是固定一种报表工具,但是不同的客户需求不同,不得已需要不停的变化展现工具;不用BI工具,自己开发应用,如果采用多维数据库,则需要程序员熟悉多维数据库的SQL语法,增加了开发的难度;基于关系型数据,采用通用的查询工具又往往面临着查询性能问题,报表的开发似乎成了一个死结。重复劳动、产品通用性差、查询性能差等问题是当前所面临的一个重要的课题,特别是对于大型的管理系统,多变的查询需求和海量数据处理,往往成为项目迟迟不能验收的一个最重要因素。
本文参照数据仓库建模的思路,解决查询性能问题,采用关系型数据结构,使用和业务系统通用的Java开发,给出了一个建立简单清晰的数据模型的方法。
在数据仓库建模中经常会采用空间换性能的方法,需要汇总的数据不是临时汇总而是提前汇总好,比如销量指标,其年累计、同期、上期、计划、实际、增长比例等提前汇总计算好,提高查询速度,在此简单介绍几个基本的数据仓库概念:
星型模式:(也称为星形连接的模式,数据立方体,或多维模式 )是最简单的样式数据仓库架构 。星型模式由一个或多个事实表中引用任何数量的维表
维表:维度表可以看作是用户来分析数据的窗口,维度表中包含事实数据表中事实记录的特性,有些特性提供描述性信息,有些特性指定如何汇总事实数据表数据,以便为分析者提供有用的信息,维度表包含帮助汇总数据的特性的层次结构。
事实表:事实数据表可能包含业务销售数据,如销售所产生的数据,事实数据表通常包含大量的行。事实数据表的主要特点是包含数字数据(事实),并且这些数字信息可以汇总,以提供有关单位作为历史的数据,每个事实数据表包含一个由多个部分组成的索引,该索引包含作为外键的相关性维度表的主键,而维度表包含事实记录的特性,在本文中称为汇总表。
为了更好的理解本项目的思路,以下以客户关系管理数据模型为例,按照对象关系模型建模,主要的业务对象包含供应商、商品;客户、客户经理、客户业态;销售订单、采购订单等基本业务对象,主要的汇总表包含客户商品日帐(即客户每天每个商品的销售汇总)等,如下图所示:
图 11数据对象模型示例
另外在本文中提到几个指标:销量,是在一段时间内客户购买的数量;上柜率,是指一个月内购买某一个商品的客户数占所有有效客户数的比率。即上柜率=本月购买本商品的客户数/有效客户总数。
根据当前所面临的问题,参考数据仓库建模理念,从以分析指标入手,建立指标模型,然后根据汇总维度建立维度矩阵模型,最终结合指标模型和纬度矩阵模型建立指标矩阵模型。
在考虑建立那些汇总表之前,首先确定那些指标是原始指标,即已经存在的指标,不再需要进行逐级汇总,可以直接使用的指标,这些指标属于原始指标,可以直接作为汇总表的原始数据。然后把不能汇总的指标尽量分解为可以汇总或者可以计数的指标,以便于进行数据汇总和查询(这一点对于简化模型很重要,可以把大部分指标分解为可以进行汇总计算的指标)。整理好所有的指标之后,通过指标进行分类,建立元指标和扩展指标,最终建立指标树模型:
- 原始指标,从其他系统获取或者采集的原始数据,为原始指标,原始指标是其他指标汇总指标的基础。
有些指标是不可以汇总,但是也无法分解,因为每个级别之间不是汇总关系,一般是单独设置的。比如计划,并不是逐级汇总上去的。因此每一级的指标都是原始指标。有些指标是从外部引入的,因此并不一定从最基础的地方开始汇总,比如系统外的数据,GPD、人口指标,可能直接从一个某一个级别开始统计,更细节的数据没有或者没有必要。因此原始指标并不一定就是从最细粒度开始汇总的。
以上两种情况,需要把指标设置为原始指标,即从从其他系统获取或者采集的指标。
- 计算指标,将不可以汇总、计数的指标分解到可以汇总的指标,比如上柜率,可以分解为客户总数和购买本商品的客户数,在最细粒度数据客户方面可以分解为是否上柜(可以计数),比如毛利率可以分解为毛利和金额。这一点很重要,只有进行类分解之后,后续的汇总和查询才可以大大简化。被分解的指标称之为计算指标。
- 元指标:首先根据业务报表需要,对所有的指标进行分类,找出元指标,元指标是不含有任何维度信息的,比如销量、金额、毛利、上柜率等。一个企业可能有上百个指标,为了便于管理,可以对指标进行分类管理,如销售类、财务类、人力资源类等。
- 扩展指标,元指标是基本的指标,但实际应用中,根据指标在不同的时间维度、或者某种算法,可以“模式化”很多扩展的指标,如:
- 年累计、年实际···
- 月实际、同期、上期、同期增长、环比增长、月累计···
扩展指标是某元指标的一个“模式化”扩展,适用于所有相关的指标。比如销量,可以有年累计销量、年计划销量、年实际销量、月实际销量、同期销量、上期销量、销量同期增长、销量环比增长、月累计销量等。这种模式化,通过分析会发现基本上可以适应到大部分指标(如金额、毛利),通过扩展指标,可以建立一个矩阵,大大简化指标体系的复杂度。
序号 | 指标 | 年累计 | 同期 | 同比 | 上期 | 环比 | ··· |
1 | 销量 | 有 | 有 | 有 | 有 | 有 | |
2 | 金额 | 有 | 有 | 有 | 有 | 有 | |
3 | 毛利 | 有 | 有 | 有 | 有 | 有 | |
4 | 毛利率 | 无 | 有 | 有 | 有 | 有 | |
··· |
表 1基于时间维度的汇总表
维度矩阵模型
- 基础维度表,基于对象关系模型(详见《基于面向对象(OO)的数据库设计模式探讨》),建立基础维度,以及基于基础维度的原始事实表。基础维度包含日期(日)、数据拥有者(所有者,客户、人员、部门)、商品等(如图1所示)。其中日期维度是必须的,因为汇总表都是基于日期维度进行汇总的,没有日期的表是基础维度表。所有者也是是必须的,因为每个数据一定是某一个所有者所拥有。除此之外的维度是可选的,比如商品,可以有不含商品维度的客户月汇总表,包含商品维度的客户商品月汇总表两个。
根据星型模式建模理论,基础维度应该可以获取所有相关信息,不需要在关联其他的维度,如客户维度表,里面应该有客户经理、销售部门、客户类别等所有相关的信息,便于提高查询效率。
注意,要把日期看成一种普通的维度,如月份,实际上也是一种“分类”,如201001,代表2010年1月,但是还可以直接用01代表一月,这样后期报表处理就会简化。
- 原始事实表,对应着对象关系模型中的流水实体对象,流水实体对象按照时间进行汇总之后的为事实表,如:客户商品日表;供应商商品日表,仓库商品日表、考虑到行政区划信息比较稳定,如GDP等,直接按照年表建立,即行政区划年表,作为最原始事实表,当然根据需要,也可以建月表。
理论上,所有的原始事实表建立之后,所有的汇总数据都可以直接查询出来了,但是考到性能问题,通过空间换时间的方式,按照维度的不同方向进行汇总。
- 维度矩阵模型,基于原始事实表,根据基础维度,在基础维度的不同汇总方向上建立维度汇总关系模型,如客户商品日表的汇总模型可以在不同维度方向上进行汇总,
首先是在日期维度
-
- 日-月-年
- 日-月-季度-年
- 日-周-年
如下图所示,可以分别建立不同的汇总表,其中常见的是日、月、年等。
图 12基于时间维度的汇总表
在客户维度:
-
- 客户-客户经理-部门经理-公司
- 客户-客户业态
如下图所示,通常按照组织机构建立汇总表。
图 13基于时间、客户维度的汇总表
在产品维度
-
- 商品-品牌-供应商-省份
- 商品-品类
- 商品-大类
图 14基于时间、客户、商品维度的汇总表
维度矩阵模型,实际上是维表在不同的可以汇总的方向上的笛卡尔乘积,其中有些是不需要的,如上图所示,根据这个模型,可以列出所有需要的汇总表。
维表的建设,可以参考当前比较成熟的建模方法,比如经常见到的数据高阶建模,一般分为参与者、地点、产品、交易等,本文不再详述。
指标矩阵模型
- 指标矩阵模型,分析每一个元指标及扩展指标在维度矩阵模型中是否存在,并根据指标进一步完善维度矩阵模型。有些指标并不是在所有的汇总表中存在的,比如上柜率是月度指标,所以在所有的年表、日表中是不存在的;比如日表中不需要同期、上期,但是年累计、月累计等指标可能是需要的。
同维度矩阵模型一样,指标矩阵模型是在维度矩阵基础上的笛卡尔积的笛卡尔积矩阵,数据是很庞大的(这也是为什么建立这个模型的原因,通过这个模型,可以建立更加容易理解的数据模型),但是并不是每一个指标在不同的矩阵中都是存在的,需要根据这个模型来分析哪些指标是存在的,哪些指标是不存在的。
在最终确定的模型中,有些数据表可能因为数据量很小,不存在性能问题,但是考虑到统一风格,统一处理方便性,全部按照一个思路,即一个“模式”,这样程序开发就会简单。
- 对于指标灵活多变的,建立基于指标的汇总表,将每个指标的值存放在列上,指标可以灵活增加。详见对象关系模型中不定属性对象的描述。
通过以上方式,即可建立一个汇总表模型,但是在实际建模过程中会出现一些特殊情况,如过于个性化的指标,不好计算,则作为原始指标来看待,单独进行汇总处理。有些指标因为维度值的变化不同,比如客户经理因为人员的更换以及客户所属客户经理更换,同期销量,实际上可以有两个值,一个是所管理的当前客户的同期,一个是本人同期管理的客户的实际值,因此需要根据需要,看看取哪一个指标。
根据“模式化”的思路,可以进一步把指标矩阵模型进一步进行扩展,有汇总数据,一般会对应着有一个计划数据,结合以上思路,可以进一步建立一个计划、汇总模型的“模式化”框架,本文不再详述。
为了更好的让指标矩阵模型发挥作用,以下分别从存储设计、性能角度及实际开发过程中的应用功能来看本模型的应用。
根据查询频次,在不同的维度方向上确定是否需要建立汇总表进行物理存储,对于不经常用的数据,可以采用实时汇总的方式,实时汇总基于最近的维度汇总表进行汇总的方式,比如查询客户商品季度汇总,可以直接客户商品月汇总表中汇总数据;查询公司客户业态月汇总数据直接从公司客户商品月汇总表中获取数据。
在数据查询的时候建议通过视图获取数据,一方面可以解决计算指标的问题,通过视图,把计算指标直接封装,二是可以通过视图实现部分物理存储,如客户业态商品汇总表,可以通过视图的方式进行汇总,而实际上并没有进行物理存储,适应于不是很常用的一些汇总、数据量比较少的汇总表,这些汇总可以通过设置查询一次存在缓存中的方式,进一步优化。
如果字段比较多,可以按照业务主题,分成多个表,在查询的时候通过多个表分别获取数据。按照以上模型建立的汇总表,同样级别的数据可能会存放在不同的表中,比如客户的销量信息和客户的上柜率可能是存放在不同的表中,如果在一个报表中同时查询这两个信息,就需要同时查询两个表,可能会存在性能问题,解决这个的办法是在查询的时候需要考虑如何优化查询性能,比如在考虑从多个汇总表表获取数据,然后合并为一个,可以先建立几个临时表,分别把需要的数据从各个地方获取存放在临时表中,然后在从临时表中获取数据,同时写入到一个表中,而不是先写一列,然后在修改,这样性能会比较差。
是否建立汇总表,可以通过在这个维度上是否有大量的减少, 比如客户经理对客户来说,一下子就减少了200倍的数据,所以汇总时值得的。如果是10倍,可以不汇总,这需要根据实际数据来分析。10000万的数据和1000万,性能还是会差别很大的。
通过前文所提到的表结构方面的优化,从查询性能角度来看,本模型主要从几个层面,采用空间换时间的思路,进行了优化:
基于星型模式的优化:建立简单星型模式,设置了维表,通过维表的冗余存放,减少的维表之间的关联,取消了雪花模型带来的性能问题。
基于指标的优化:建立指标扩展模型,同时查询的数据存放在表的一行中,可以一次获取,减少查询的次数,如同时获取同期、上期数据,避免数据的多次查询。
基于索引的优化:直接在事实表中建立外键,分类汇总不需要关联更多的维表中,可以直接进行查询。同时直接在事实表中建立外键之后,可以保留历史痕迹,完整的反应当时的数据情况,如客户的客户业态更换之后,还可以按照客户当时所属的客户客户业态进行统计。
基于汇总表的优化:根据维表的不同汇总方向,建立多级汇总表,汇总的数据直接在汇总表中查询,实现数据的优化。
灵活查询系统建设过程
基于汇总表体系,建立灵活查询系统,是本模型的目标之一,按照组件化的方式,可以将灵活查询系统分成查询组件、数据获取组件、数据展示组件、数据汇总组件、元数据组件。数据库层面还需要完善的内容包含数据权限、元数据两个部分,数据权限用与限定使用者看到的数据范围,元数据用与描述本模型,如下图所示:
图 15灵活查询系统组件模型
灵活查询系统建立之后,可以实现自动的数据汇总,自定义查询条件和查询显示结果,如果完全实现灵活查询系统,需要一个漫长的过程,而且很可能因为工期太长,系统过于复杂,最终导致系统开发会失败,可以分步建设,逐步实现:
首先建立基于指标矩阵模型的数据库,基于本数据库进行查询,具体的查询可以采用原来的查询方式和报表展示,数据汇总可以通过直接写程序或者手工汇总。
建立元数据管理,对数据模型进行管理,基于元数据管理建立独立查询模块,实现定义各种查询条件,输出结果为一个标准化之后的查询的XML,然后根据查询XML生成查询结果。查询模块可以进一步完善,如保存查询条件等。
建立数据获取模块,数据获取模输入条件为标准化之后的查询的XML,输出也是标准化的XML,进一步将数据获取模块进行分离,只要输入一个查询的XML,就可以获取一个查询结果,并以XML方式输出。
建立数据展示模块,根据XML格式自动展示,最终实现自定义数据展示。
建立数据汇总模块,基于元数据,实现自动汇总。
通过以上分析可以看到,虽然整个灵活查询系统体系非常复杂,但是可以分解为不同的组件,分步建设,逐步实现。当然,也可以直接采用成熟的商品软件,特别对于大型的项目,可以直接部分或者全部采用商品软件,如IBM产品体系,可以采用:数据汇总,采用ETL工具,如Datastage,数据展示采用Cognos等,进一步简化系统的开发,如下图所示。
图 16基于IBM系统软件的灵活查询系统
以上根据前文提到的指标矩阵模型,就模型表结构设计、性能优化及灵活查询系统建设做了一个简单说明。
通过本文的介绍,描述了一个基于指标矩阵模型建立汇总表的方法,主要的目的是“模式化”汇总表的建设,建立清晰明了的数据模型,本模型的主要适用场景为《面向服务体系架构(SOA)和数据仓库(DW)的思考》中共享库的建设以及为基于关系型数据库,采用Java开发的报表查询系统建立一个模式化的清晰可读的数据模型提供一个方法。