mul*_*uin 5 erd normalization database-design
TLDR;以下场景的最佳设计选择是什么,每个设计在极大数据量下会如何反应?
我有使用大型政府数据库系统服务 24/7 数据收集、处理和报告的经验。浏览所有不同设计的模式并了解所有这些不同的人设计的所有这些功能如何以某种方式混杂成一个有效的解决方案是很有趣的。就像我相信你们中的一些人知道的那样,有趣的戳时间是一种奢侈,而且大多数周期都是务实的,让系统保持活力而不是改进设计。
我一直在建模一个新的数据库系统,并想对如何关联这些实体有一些想法。
我们有四个实体:
CLIENT
EMPLOYER
PRACTITIONER
PHONE
电话号码按用于接听电话的技术进行分类,所使用的技术通知数据格式限制。
描述字段指示电话的主要用途;家庭、工作等。
PHONE
为CLIENT
, EMPLOYER
,PRACTITIONER
让我们从糟糕的设计开始,然后从那里开始。去规范化所有的电话号码!
CLIENT.Phone1Number
, EMPLOYER.Phone2Type
, PRACTITIONER.Phone3Description
;结论:select * from 'no_thanks';
对于可以关联电话号码的每个实体,创建一个桥实体将它们组合在一起。
PhoneNumber
在需要时可以使用桥接表;不需要 JOIN 即可PHONE
FAMILYMEMBER
需要电话号码,则必须创建新的桥接表结论:也许,取决于维持关系的难度
修改PHONE
以包含CLIENT.ClientID
, EMPLOYER.EmployerID
, 的外键PRACTITIONER.PractitionerID
。
FAMILYMEMBER
需要电话号码,则必须在PHONE
结论:在我看来似乎是最强的设计
如果我真的必须选择,我会说你的第二个选择(建造第n座桥)将是我最喜欢的,因为它很干净并且遵守规则。虽然您的第三个选择虽然减少了表的数量,但它实际上在电话表中带来了带有空值的“冗余”列,并且这种设计是“易失性”的,因为如果您需要添加新的电话所有者类型,您需要在 [Phone] 表中添加一个附加列。
以另一种方式,我将创建一个如下所示的“桥”表(以 t-sql 为例):
create table PhoneOwner (ID int identity primary key
, OwnerID int
, OwnerType varchar(20));
Run Code Online (Sandbox Code Playgroud)
因此,对于 [Phone] 表,我将添加一列 PhoneOwnerID,它引用 [PhoneOwner] 表的 [ID] 列。在本例中, OwnerType列可以具有“客户”、“雇主”或“从业者”的值,或者将来的其他值。(当然,我们可以创建[OwnerType]表来保存这些值,并在[PhoneOwner]表中放置一个FK来引用这个[OwnerType]表)
这种替代设计的问题在于完整性检查,例如如果OwnerType = 'Client',我们需要确保OwnerID的值确实存在于[Client]表中,尽管这可以通过应用层或通过触发器来实现此类业务规则。
但我不得不承认这是对严格完整性(通过 FK)规则的妥协,好的一面是它以某种方式实现了更好的灵活性,并且减少了表设计中的混乱,这将导致“冗余”列中出现许多空值。