博主认为,设计的依据在于三种因素:
1、正确
1、表达清晰
2、效率
针对数据库的设计,经常考虑两个因素:
1、实体成为属性还是表
2、二元关系还是多元关系
第一条不用多说,如果设计出来的模型不能正确反映想要表达的实体和各种约束,这自然是失败的设计。至于第二条,如果不注重表达的情绪,一上来就想去考虑有关效率的细节,这样做很容易陷入迷惑,表达清晰的设计容易理解和维护。容易维护的设计不一定能针对实际需求达到高效率,所以需要优化,比如修改关系模式避免连接操作,以及在物理上建立索引。
首先按照最清晰的方式来进行设计:每个实体集都单独对应一张表,并且采用多元关系。然后再来考虑效率问题。
如果每个实体集都对应一张表,但如果发现一个实体本身几乎不包含信息,并且与这个实体相联系的实体比较少,比如搜索引擎中的一个term或者url字符串,我们实在是没有必要再为这个实体创建一张表,只需要作为其他实体的某个字段就可以了。不需要每个实体都创建一个 ID 字段,因为实际的查询用不到这个id字段。如果视图用 id 作为一个term的标识,与其他实体相联系,就带来了连接的代价。总之,应该将字段很少并且和其他实体联系少的实体删除,这样的实体本身只在概念上存在,只出其他实体的字段中;应该将经常需要连接的联系表删除,直接在一个实体上添加外键字段。
一般来说只要三元关系不过分太长,找不到把多元关系拆分成为多个二元关系的理由,无论是从清晰的角度还是从效率的角度,多元关系往往更加清晰的表达现实世界的概念,同时又避免了连接操作。多个二元关系意味着连接操作,连接操作一般比简单的过滤查询费时太多了,建立索引可以缓解查询问题,它的执行时间不能和连接操作相提并论,比如说考虑用户-商品-评论关系,某个用户对某个商品不太可能发表太多的评论,所以三元关系表也不会太长。当然要得到准确的答案还是得根据实际场景进行测试,定性的分析终究不能作为最终判据,一般还是先按照最清晰的方式设计。
两个二元关系不能表达三元关系!连接操作实际上是找连通路径的过程,三元联系关系表的每条记录代表了一条长度为2的路径。这些路径不可能用两个二元关系表达,因为二元关系的连接操作可能会多出来很多本不存在的三元联系。必须要引入引用了每条路径的中间实体,表的长度不会有任何减少。
实体成为属性还是表?二元关系还是多元关系?相信已经有了更清晰的认识。在概念设计阶段我们要让设计清晰的表达概念,但是在实际逻辑设计阶段我们要避免执行可以省去的连接操作。
ps: 一个二元关系对应一个拓扑结构:二分图的实例。如果二分图的任意一个连通分支都是一颗根树,那么这个关系就是一对多、多对一、一对一关系,可以只有一个字段是主键;否则是多对多关系,两个字段都必须是主键。
树和二分图都是拓扑结构。