经过概念模型设计、逻辑模型设计两个阶段,接下来就是物理模型(Physical Data Model)设计。物理模型设计过程中,大部分思考和设计的焦点是“性能”这一关键词。
物理模型设计要说的内容并不会特别多,在实际设计的过程中,建模高手往往融会贯通地将这些考虑都前置到了逻辑模型设计阶段,在物理模型阶段只是做补充和复查。不过,为了清晰地界定逻辑模型和物理模型的设计边界,还是需要从理论的层面详细说明一下设计过程的区别。
这个阶段的开始,意味着对逻辑模型的修改大部分已经结束,数据模型的整体框架已经稳定,需要从技术角度来完善逻辑数据模型,补充并设计成一个能够满足未来开发和使用需求的物理模型。
所以,物理模型设计过程可能会需要对逻辑模型中部分实体做一些调整,具体哪些设计会影响到逻辑模型后面会做一些说明,只是希望你不要把物理模型作为一个独立的产出物。
考虑技术因素对逻辑模型做一些调整是一个很自然的事情,并不是说逻辑模型设计得不好。在开发的过程中,也会发现有一些设计上考虑不全面或者根本考虑不到的情况,这个时候要保证设计和实现的一致,都有可能需要对模型进行维护。So,不要害怕变化,要拥抱变化。
▌物理模型是指导开发的工具
物理模型设计时需要具备一些数据库管理员(DBA)和数据库性能专家的视角,对数据建模师来说,在概念模型和逻辑模型设计过程中考验的是对业务的理解程度和数据模型设计能力,在物理模型设计过程中则考验的是对技术的理解。
但是,不用担心,刚开始可能会有一些“恐惧”,其实也没有那么难,在设计过程中可以和那些“技术大咖”多请教在开发和实现过程中,数据是如何处理和使用的就行。
概念模型是讨论业务需求的工具,逻辑模型和物理模型是指导开发的工具,所以,在设计的过程中也必然需要达成与技术人员理解上的一致,帮助他们更好地理解设计的初衷。
▌物理模型设计与数据库设计不同
物理模型设计和数据库设计(Database Design)两个概念还是有一些不一样的。
物理模型是一个模型,在逻辑模型设计的基础上,主要考虑数据库使用的性能、开发便捷性,对结构进行补充和完善,还会添加一些物理对象的设计。
而数据库设计包含了物理模型设计,也包含了从数据库管理角度对数据库使用的架构、存储容量和存储参数等方面的思考。
所以,数据建模师和数据库管理员(DBA)的工作职责不一样,在设计的过程中考虑的也不一样。
▌物理模型设计的关键点
物理模型设计时关注的重点始终是性能,在保证性能的前提下,再考虑一些开发的便捷性。物理模型设计阶段通常会考虑以下几个方面。
实体整合和拆分
实体整合一方面是考虑模型中设计为一对一关系的实体是否有必要整合成一张表,另一方面就是考虑结构相似但独立存在的实体是否有必要整合成一张表。
实体拆分则相反,考虑的是哪些实体需要拆分成多个实体。一般拆分的方式分为水平拆分和垂直拆分,水平拆分是对未来存储数据的拆分,实体的结构不变,例如,“男”客户一个实体、“女”客户一个实体,两个实体中包含的属性是一样的;垂直拆分是对属性的拆分,把一个实体中的十个属性分别拆分到两个实体中,可能一个实体里包含七个,另一个实体里包含三个。
所以,实体的整合和拆分其实是相对的,对于初学者来说有时候很难判断什么时候整合什么时候拆分。
我的建议是,设计过程中尽量先按整合的思路来设计,在这个阶段参考以下基准进行拆分即可。
首先,判断实体中未来存储的数据量以及数据量增长的特征,如果很大而且增长很快,从业务角度找到一个拆分成多个实体的基准,拆分即可。
其次,判断实体中一些具体属性的特点,是否需要独立实施安全保护措施?是否被访问或变更得很频繁?是否在一个业务处理过程中需要都被使用到?数据是否同时被创建?等如果有这些特殊的设计要求,果断拆分。
记住!模型结构的调整会导致性能的差异和使用方式的不同,所以,要充分地“三思而后行”。对于建模高手来说,在逻辑模型设计阶段可能就已经预判了这些因素。厉害呀~
子类型转换
子类型是逻辑模型中的概念,物理模型中并不存在这个概念,只是在来到物理模型这个阶段的时候,要确认子类型转换是否正确,并且理解子类型转换的方式。
子类型的实体转换成物理模型表的时候,是一对一还是拆成多张表?
一般在建模工具中为了在保持逻辑模型和物理模型之间关联性的同时简化这个转换过程会有自动转换的功能,但是要确认一下默认的转换方式。我的建议是一对一来理解,不然管理和操作起来就很繁琐,并且也不建议将逻辑模型和物理模型之间的映射搞得很复杂,彼此之间的依赖和关联性还是很强的。如果你需要的是一个企业级的逻辑模型,那建议还是单独维护一个独立的企业级逻辑模型。
子类型转换的时候还要注意子类型属性的变化,子类型中的属性无论是必填还是选填,都会转换成选填。为什么?以后我再慢慢给你展开说吧。
反范式化(Denormalization)
范式化是去除冗余,反范式化是增加冗余。
干嘛搞得这么麻烦?为啥要先去掉再加上?就是为了防止乱加呀~
冗余会破坏数据的完整性,会导致数据错误、不一致,所以要去除,但是,凡事必有利弊权衡,范式化把冗余去得太干净了,用起来就不方便。所以,关键是什么情况下需要增加冗余?举几个例子吧。
查询的时候需要经常需要计算,而且计算起来也比较麻烦的字段,可以提前算好存起来。
查询的时候经常需要关联其他表才能查询到的字段,可以复制到一张表里存起来。
实际设计的时候会考虑更多的场景,但是,上面两个例子基本上体现出来一点就是,需要增加冗余的情况大多数都是需要预先计算好或者预算存储到一起的场景,也就是技术大咖们经常说的“用空间来换时间”。
反范式化的详细案例以后再说,需要你记住的是,物理模型并不会将所有场景都考虑到,在开发和运行系统的时候也会产生一些性能问题,为了解决性能问题通过合适的方法在最小的范围内进行反范式化设计才是最关键的。为的就是,避免冗余做得太多太泛滥,导致数据完整性出问题。而且,也要时刻铭记反范式化带来的影响需要考虑如何通过程序手段来弥补,一处变更了其他几处也要同时变更。
其他物理对象
在物理模型设计阶段要考虑的其他物理对象也有很多。每一种物理对象的设计都需要一定思想的指导,本文不会说太多,这些都需要在过程中一点点学习,在这里就简单说一下吧。
在逻辑模型中叫主标识符(Primary Identifier)的概念,在物理模型中叫主键(Primary Key),但是,这两个概念又不完全一致,在数据库对象的角度来说,主键是一种约束,包含了唯一性约束和非空约束。在实际开发的过程中,随着数据库特性和开发规范的要求,需要用不同类型的设计。比如,有些开发规范中会要求数据库中不允许使用主键,这个时候说的是不允许创建主键约束,因为主键属性本身就是存在的。有的会要求不允许使用联合主键,需要使用自增主键等类似的要求,这些都要在物理模型设计的时候考虑如何设计和应对。
分区(Partition)有很多种类型,分区设计虽然也有性能方面的考虑(分区裁剪技术),但是,也有运维管理和高可用性方面的考虑。在分区设计的时候,就会涉及分区键是什么?备份策略是什么?各个分区的数据量是否均衡?全局索引和本地索引怎么设计?等等一系列技术要点。除了分区以外,在MPP数据库和大数据平台中常见的分布键、分桶键等都是类似的。
表存储类型也是要考虑的点之一,一般来说表级别设计的存储方式有堆表(HOT:Heap-Organized Table)、索引组织表(Index-Organized Table:IOT)、聚簇表(Clustering Table)这几种方式,具体的优缺点和选择基准就不具体说了,物理模型设计还是需要一定对数据库技术的理解。
除了这些以外还有索引、视图、约束等更加具体的对象设计每一个技术点都有一些不同,在物理模型设计阶段不可能考虑得绝对全面,针对非常明确的内容可以直接设计在物理模型中,不明确的那些可以在后续使用阶段中补充,但是,前提一定是以解决性能问题为主。
比如,索引的设计在物理模型阶段大多只对主键字段和外键相关的字段上创建索引,在开发阶段产生性能问题的时候再详细考虑更为合适,一方面是因为索引的设计需要参考具体的执行计划(Execution Plan)和统计信息(Statistics),另一方面是因为索引过多反而会导致性能更差。视图虽然能提高一定程度的开发便捷性和隐私性,但是不同数据库在生成执行计划的时候对视图的分析能力不同,没有思考地使用也会引发性能问题。
系统字段
系统字段是指类似于“创建人、创建时间、最终修改人、最终修改时间、数据迁移时间”等从管理或数据同步等方面考虑需要的一些字段,这些字段的设计不建议在逻辑模型设计的过程中考虑,一般来说系统字段可以理解为落实设计规范,在数据模型最终阶段考虑更为合适,很多工具中都有一些方便建模师批量添加和调整的功能。
织巢鸟
恩核自主研发的企业级关系型数据库建模软件,拥有100%自主知识产权。本产品功能聚焦、支持多人协作高效建模、多方平台对接、数据资产共享、标准智能落地、全生命周期管控、安全稳定、模型云化、模型知识库共建共享,可实现事前源头智能落标,事中模型健康度自动监控和事后模型自动差异比对以及模型可视化呈现,实现客户对产品的自主可控。