数据库设计概念模型要不要建?
记得上学时,学习数据库相关课程中要求我们一步一步按照“需求”-->概念结构设计-->逻辑结构设计-->物理结构设计的步骤完成。但来到公司实际项目中时,我却发现几乎没有一个项目是完全按照这个步骤来建立数据库的。很多项目基本就是从需求中直接获取信息,然后进入逻辑结构设计阶段最后到片面的物理结构设计阶段,直到数据库可以使用,反复迭代该过程。
我从来没有见过哪个项目画过一张概念结构设计阶段最重要的产物--E-R图,但我能见到一张由PD工具画的关系模式图,然后“工程师”们就用它生成数据库脚本,此时数据库建模算是完事了!至于物理结构设计阶段的一些工作,诸如索引和优化等那是以后的事情,甚至根本不予考虑。
之所以这样,我觉得可能是出于以下几个原因。其一,我觉得主要可能是工期上不允许你花费这么多功夫,出一个完美的设计文档。其二,是没有必要按部就班的设计数据库,靠自己的经验足以!其三,就是压根设计人员不懂这么个设计方法。
我今天主要是想说下这个概念结构设计要不要做的问题以及怎么做才是合理的。
概念模型一定要做,这个阶段的最重要的产物就是E-R图,也就是实体联系图,这个或许也就是我们开发系统时常说的“实体”(Entity)这个词的源头了,实体这个概念是一个早期的概念约1976年,但面向对象编程技术真正兴起发展成熟应该在90年代。其实在我看来“实体”和“对象”是同一个概念,只不过E-R图数据库建模流行,才保留了这种叫法。而且数据库表也不叫什么“实体”,但可以叫一个“关系模式”,所以我就纳闷了,为什么一开发系统“工程师”们都在用实体这个词称呼与数据库表对应的类呢。我觉得实乃E-R图建模的流行惹的祸!
另一个困扰我的问题是,既然大家都喜欢称呼“实体”(Entity),那为什么“工程师”们设计数据库的时候设计文档几乎看不到E-R图呢?其实我觉得E-R图是数据库设计必不可少的一步,尽管很多工程师忽略它,无视它。在我看来系统越是复杂就越需要建立E-R图模型,即便是小系统,建一个也费不了几分钟。在我看来,越是复杂的系统没有一个好的E-R模型,它越经受不起业务变更的考验,许多测试出来的业务Bug,多半是因为建了一个不科学的数据库,这样的系统可扩展性差。为什么我这么肯定呢?且听我慢慢道来。
首先发明E-R图的人是伟大的,因为他给了我们一个强大的武器,让我们在设计数据库时有一个章法可循,而不是一味的依靠自己的经验完成,它是科学的方法论。他有什么作用呢?
在需求阶段得到的应用需求应该首先抽象为信息世界的结构,才能更好的更准确的理解需求。所谓抽象就是对实际的人、物、事和概念进行人为处理,抽取所关心的共同特性,忽略非本质的细节,并把这些特性用各种概念加以精确的描述。
前面说了一堆概念,我还是来说点实际的东西。我们经常遇到这样一个问题:这个属性是做为这张表的一个属性好呢,还是需要单独抽离出来作为一张表然后用外键关联好呢?比如说职工这个实体。按照一般的原则是:现实世界能作为属性对待的,尽量作为属性对待。但这是有一些条件判断的,这里给出两个准则。
1、作为“属性”,不能再具有需要描述的属性。“属性”必须是不可分隔的数据项,不能包含其他属性。
2、“属性”不能与其他实体有联系。
如下图所示:如果职称不需要进一步描述的话,可以画到上图为止即可。但是一般说来如果系统要解决这个问题域的业务,根据现实世界的信息情况可知,职称应该要进一步描述其性质,职工的工资一般是和职称挂钩的,包括其他福利。当然,是不是非得挖掘出现实世界中问题域中的所有信息呢?答案是未必的。主要还是看客户的实际情况是怎样的,即便客户将来需要深挖深掘,那改动起来也是一个局部的,不会牵扯到其它实体已经存在关系。这样的模型是经得起需求变更的考验的。
说了那么多,大家会问,建立这个模型有什么用,能直接转化成数据库表吗?我的回答是可以的,E-R模型是概念层的,它可以转化为某种数据库模型,可以是层次型数据库、网状型数据库以及关系型数据库等。由E-R图转化为某种数据库模型,都有对应的方法论,就是一种转换规则。这个我就不在这里啰嗦了,很多教科书都讲了怎么转换。
这样一个E-R 模型是我们设计关系数据库的依据,在逻辑结构设计阶段映射成关系模式后,可能还需要考虑关系模式规范化的问题。关系数据库最基本的就是要满足1NF,不满足的就不是关系数据库了,它的要求就是关系模式的每一项都必须是不可再分割的。比如说,如果你的E-R模型是上面下图中的,那么你必须把职工和职称分别独立成一个关系模式(相当于两张表)。不能将职称直接作为职工的某个属性。
规范化程度越高一般会导致关系模式越多,查询效率降低,但好处是数据冗余降低,各种插入删除异常消除。我认为一般能达到2NF或3NF就是一个折衷方案。一般为了性能的提高,需要进行反范式设计甚至添加冗余字段,这些都是合理的,但千万不要乱用,如果你的系统没有什么性能瓶颈,就不要做这些工作。不管怎么样。规范化也好反规范化也好,E-R模型是不能变的,它是设计数据库修改数据库的依据。
我们设计的关系模式(表),一般是采用代理键,而不采用自然键,之所以这样设计,是因为这样可以让每一个数据项都有唯一简单的标识,表之间的连接也会大大简化。
最后,我想说出我的一些其他想法,我觉得领域建模和这个E-R建模颇为相似,都是对现实世界信息的抽象,都是描述对象之间的关系,当然领域建模中的专业词汇可比E-R建模多多了,但领域模型基本包涵了E-R模型中的元素。实体间的one-to-one、many-to-many、自关联、继承等,领域建模都有。所以我的观点是可以将E-R模型看作是一个不完整的领域模型。
如果这样的观点成立,那么我们以后可以先建立领域模型,然后将需要持久化的领域对象抽出来建立等效的E-R模型,方便对比。这样就能很好的解决一个问题就是,由ORM工具生成的实体类可以看作是领域模型的一部分,虽然不完善,但像是C#语言有Partil类特性,可以自己进行补充,给这些“实体”类添加领域逻辑行为,这样就可以将实体和领域对象统一起来管理而不需要非得分开维护管理啦!(*^__^*) 嘻嘻。