1总则
1.1目的
本文档用于指导数据建模的具体实施工作。
1.2简介
本规范规定了基于广联达应用开发平台(以下简称:开发平台)开发的组件的数据建模设计的标准及规范,包括
1.3适用范围
本规范适用于基于广联达应用开发平台开发的组件的数据建模工作。
1.4术语、定义及缩写
概念模型:概念模型是一个抽象的宏观层次(高层次、粗粒度)的业务模型,用于定义核心的业务概念实体和彼此的关系,最常用的是“实体-关系”图,所以在概念模型中最重要的对象是实体和关系。这一阶段主要工作是通过需求分析,明确需求所涵盖的业务范围,然后对需求范围内的业务及其间关系进行高度概括性的描述,把密切相关业务对象进行归类,划分为多个主题域。主题域是模型针对的业务的某一关注领域或关注点,同一个域内的实体具有高内聚性,不同域的实体之间具有低耦合性。
逻辑模型:逻辑模型是概念模型的延伸、分解和细化,表示概念之间的逻辑次序,是一个属于方法层次的模型。本阶段工作主要是根据业务定义、分类和规则对概念模型进行细化,定义其中的实体并描述实体之间的关系,产生实体关系图,然后遵照规范化思想在实体关系的基础上明确各个实体的属性。对于基础层一般采用3NF进行设计,达到数据冗余最小。对于汇总和信息子层一般采用反规范化冗余设计,快速支持数据访问和应用开发。
物理模型:主要依据逻辑模型针对具体的分析需求和物理平台采取相应的优化策略。此时会在一定程度上增加数据冗余或者隐藏实体之间的关系,是一种反规范化的处理,目的是提高数据分析的速度,适应具体数据库的容量、性能等限制。
2规范细则
2.1 数据模型设计原则
为保证模型的稳定性和对业务支持的灵活性,建模阶段将遵循以下的原则:
继承性原则:以现有用户应用系统数据模型规范作为基础,在不影响理解情况下,尽量不提出新的概念;
稳定性原则:为保证模型的稳定性,实体与规则分离,突出核心实体的描述,提出规则点,对规则本身不做详尽描述;
前瞻性原则:为保证模型的前瞻性,同时采用自底向上和自顶向下的方式设计模型,其中自顶向下主要基于业务需求进行模型设计,使其可以完全覆盖到所有需求,自底向上主要基于业务逻辑而非业务需求进行模型设计,模型设计为囊括用户现有的各种业务关系,保证在有新需求时,底层模型能够对其进行支撑;
兼顾实际原则:在模型设计时针对当前用户系统建设的实际情况进行调研,保障模型能正常落地;
扩展性原则:模型的扩展包括实体属性的扩展和实体关系的扩展,模型设计为实体内只保留最细粒度的基本属性,粗粒度或上层的属性通过雪花结构的属性依赖关系实体来表现,这样在扩充属性或者扩充实体关系时,只增加表现属性依赖关系的实体即可。
2.2 数据模型设计方法
数据模型设计采用自顶向下与自底向上相结合的方法进行设计。
以企业级数据标准为指导,结合生产系统相关规范及业务术语,先建立概念模型,再在概念模型的基础上进行细化设计逻辑模型,物理实现时依据逻辑模型针对具体的分析需求和物理平台采取相应的优化策略。
2.3 范式设计方法
三范式(3NF)建模是一种消除数据冗余的设计方法,数据被分成很多离散的实体,每一个实体在关系数据库中都对应一个数据表。实体是人、位置、事情或概念,这些东西具有机构部门感兴趣的特征,可以通过实体来存储与这些特征有关的信息。关系是将实体绑到一起的动词。关系不是物理的,但用于描述实体之间存在的依赖性。
第一范式:是最基本的规范形式,即关系中每个属性都是不可再分的简单项。所谓第一范式就是指数据库表中的任何字段都是单一属性不可再分,也就是说对于满足第一范式的表的字段都是对一种的描述属性,该属性都是单一的不可再分的,如人的年龄、姓名等。
第二范式:指如果一个关系模式满足第一范式且每个主属性都完全函数依赖于它的主关系键则称这个关系满足第二范式。第二范式也就是指除了主键外确保表中的每个属性列都必须依赖于主键。如人员信息表(工号,姓名,性别,年龄,岗位)其中工号为主键而岗位不依赖于学号所以人员信息表中应把岗位删掉。
第三范式:是指在满足第二范式的前提下每个非主属性都不传递函数依赖于主键关系则成这个关系满足第三范式。所谓传递函数依赖,指的是如果存在”A → B → C”的决定关系,则C传递函数依赖于A。因此,满足第三范式的数据库表应该不存在如下依赖关系: 关键字段 → 非关键字段x → 非关键字段y。例如人员表(工号,姓名,年龄,所在部门,部门电话)很明显此表满足第一范式,由于存在工号可以决定姓名、年龄、所在部门、部门电话所以也满足第二范式,而由于所在部门就可确定部门电话因此该表存在传递依赖关系故不满足第三范式。
2.4 维度建模方法
维度建模是数据仓库工程领域最流行的数仓建模经典。维度建模以分析决策的需求出发构建模型,构建的数据模型为分析需求服务,因此它重点解决用户如何更快速完成分析需求,同时还有较好的大规模复杂查询的响应性能。它是面向分析的,为了提高查询性能可以增加数据冗余,反规范化的设计技术。
2.4.1 事实与维度
在维度建模中,度量称为事实,上下文和环境称为维度。
事实表:产生于业务过程,存储了业务活动或事件提炼出来的性能度量。从最低的粒度级别来看,事实表行对应一个度量事件。事实表根据粒度的角色划分不同,可分为事务事实表、周期快照事实表、累积快照事实表。
事务事实表:用于承载事务数据,通常粒度比较低,它是面向事务的,其粒度是每一行对应一个事务,它是最细粒度的事实表,例如产品交易事务事实、ATM交易事务事实。
周期快照事实表:按照一定的时间周期间隔(每天,每月)来捕捉业务活动的执行情况,一旦装入事实表就不会再去更新,它是事务事实表的补充。用来记录有规律的、固定时间间隔的业务累计数据,通常粒度比较高,例如账户月平均余额事实表。
累积快照事实表:用来记录具有时间跨度的业务处理过程的整个过程的信息,每个生命周期一行,通常这类事实表比较少见。
这里需要注意的是,在进行事实表的设计时,一定要注意一个事实表只能有一个粒度,不能将不同粒度的事实建立在同一张事实表中。
维度表:一致性维度,业务过程的发生或分析角度,我们主要关注下退化维度和缓慢变化维。
退化维度:在维度类型中,有一种重要的维度称作为退化维度,亦维度退化一说。这种维度指的是直接把一些简单的维度放在事实表中。退化维度是维度建模领域中的一个非常重要的概念,它对理解维度建模有着非常重要的作用,退化维度一般在分析中可以用来做分组使用。
缓慢变化维:维度的属性并不是始终不变的,它会随着时间的流逝发生缓慢的变化,这种随时间发生变化的维度我们一般称之为缓慢变化维(SCD)。
2.4.2 星型架构和雪花架构
组合维度表和事实表的基本架构
星型架构:所有维度表直接连接到事实表,整个组合的形状类似于星星。星型架构是一种非规范化的架构,其数据存储存在冗余。例如考虑商品的维度表,其品牌信息在商品的每一行中都存在,包括其品牌ID、名称、品牌拥有者等。通常很多商品的品牌都是一样的,所以在商品维度表中品牌的信息被重复存储了很多次,也就是存在冗余。
雪花架构:雪花架构是对星型架构维度表的规范化。当有一个或者多个维度表没有直接连接到事实表,而通过其他维度表连接到事实表上。比如上述的商品例子,在雪花架构中,其每行仅存储品牌ID,而品牌的所有其他信息(包括品牌名称、拥有者、注册地等所有描述信息)都存储在单独的品牌维度表内。通过品牌ID整个外键,商品表可以间接获取到所有品牌的描述信息。雪花架构去除了数据冗余,节省了部分存储,但是在使用过程中复杂度增加,给用户使用带来不方便。因此在维度建模的实际中,雪花架构很少使用到。
星型架构牺牲了部分存储的冗余,但是带来了使用上的极度便捷。现在存储成本极低,多出的存储开销相比后续每次的关联计算、用户使用和学习成本来说,是非常划算的。
2.4.3 维度建模流程
选择业务过程→定义粒度→确定维度→确定事实。旨在重点解决数据粒度、维度设计和事实表设计问题。
业务过程:业务过程即企业和组织的业务活动,它们一般都有相应的源头业务系统支持。业务过程并不是指业务部门或者职能。如果建立的维度模型是同部门捆绑在一起的,就无法避免出现数据不一致的情况(如业务编码、含义等)。确保数据一致性的最佳办法是从企业和公司全局与整体角度,对于某一个业务过程建立单一的、一致的维度模型。
定义粒度:意味着对事实表行实际代表的内容和含义给出明确的说明。其实质就是如何描述事实表的单个行。如果没有明确的粒度定义,则不能进入后面的环节。如果在后面的环节中发现粒度的定义不够或者是错误,那么也必须返回这一环节重新定义粒度。最大限度地选择业务过程中最为原子性的粒度,这样可以带来后续的最大灵活度。
2.5 模型命名规范
数据库名:以下划线分割法定义,英文小写全称(不能简写)。
物理文件名:按默认名处理。
表空间名:按默认处理。
表名:以下划线分割法定义、且都以”t_”开头、英文小写全称(不能简写)。表名不使用复数名词。
说明:表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于 Entity 类名也是单数形式,符合表达习惯。
视图名:以下划线分割法定义、且都以”v_”开头、英文小写全称(不能简写)。
字段名:以下划线分割法定义,且都以”f_”开头,命名避开当前表名,全部小写。
索引名:对于主键:采用”pk_”+字段名(不带表名、不带”f_”)命名;非主键、非唯一索引:采用”idx_”+字段名(不带表名、不带”f_”) 命名;唯一索引:采用”uk_”+字段名(不带表名、不带”f_”) 命名。
函数名:以下划线分割法定义、且都以”func_”开头、英文小写全称(不能简写)。
2.6 建表规范
① 表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint (1 表示是,0 表示否)。
说明:任何字段如果为非负数,必须是 unsigned。
② 禁用保留字,如desc、range、match、delayed 等,请参考 MySQL 官方保留字。
③ 小数类型为 decimal,禁止使用 float 和 double。
说明:float 和 double 在存储的时候,存在精度损失的问题,很可能在值的比较时,得不到正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数分开存储。
④ varchar是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长度大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索引效率。
⑤ 表必备四字段:id, create_time, update_time, version。
说明:其中 id 必为主键,类型为 bigint unsigned、单表时自增、步长为 1。create_time, update_time 的类型均为 datetime 类型,前者现在时表示主动创建,后者过去分词表示被动更新,version的类型为 int 类型,表示乐观锁。
⑥ 字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循:(1)不是频繁修改的字段;(2)不是 varchar 超长字段,更不能是 text 字段。
正例:商品类目名称使用频率高,字段长度短,名称基本一成不变,可在相关联的表中冗余存 储类目名称,避免关联查询。
⑦ 单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。
说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。
⑧ 合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。
2.7 索引规范
① 所有表中不能没有主键、尽可能避免联合主键:即使是关系表,关系键必须建索引。
② 不得使用外键与级联,一切外键概念必须在应用层解决。
说明: 以学生和成绩的关系为例,学生表中的student_id是主键,那么成绩表中的student_id则为外键。如果更新学生表中的student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,外键影响数据库的插入速度。
③ 业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
说明:不要以为唯一索引影响了insert速度,这个速度损耗可以忽略,但提高查找速度是明显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。
④ 在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。
说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为20的索引,区分度会高达90%以上,可以使用count(distinct left(列名, 索引长度))/count(*)的区分度来确定。
⑤ 建组合索引的时候,区分度最高的在最左边。
说明:存在非等号和等号混合时,在建索引时,请把等号条件的列前置。如:where c>? and d=? 那么即使 c 的区分度更高,也必须把 d 放在索引的最前列,即索引 idx_d_c。
正例:如果 where a=? and b=? ,如果 a 列的几乎接近于唯一值,那么只需要单建 idx_a 索引即可。
2.8 数据类型规范
序号 | 字段大类 | 字段表示 | 数据类型 | 简写 | 说明 |
1 | 主键类 | f_id | bigint(20) | ||
2 | 名称类 | f_name | varchar(255) | v64 | |
3 | 编码类 | f_code | varchar(64) | v64 | |
4 | 小数类 | decimal(19,4) | |||
5 | 整数类 | int(11) | |||
6 | 状态类 | f_status | tinyint | ||
7 | 备注类 | f_remark | varchar(2000) | V2000 | |
8 | 日期类 | f_date | datetime | YYYYMMDD 24:MI:SS |
3附则
3.1相关规范文档
- William H.Inmon《Building the Data Warehouse》
- Ralph Kimball《TheData Warehouse Toolkit》