数据库模式 - 多对多规范化
问题描述:
我正在设计一个模式,其中一个案例可以附加多个表单并且表单可以用于很多情况。 Form
表基本上保存了在客户端呈现的html表单的结构。提交表单时,字段的名称/值对将分开存储。如何保持名称/值属性与连接表分离如下有什么价值?数据库模式 - 多对多规范化
CREATE TABLE Case (
ID int NOT NULL PRIMARY KEY,
...
);
CREATE TABLE CaseForm (
CaseID int NOT NULL FOREIGN KEY REFERENCES Case (ID),
FormID int NOT NULL FOREIGN KEY REFERENCES Form (ID),
CONSTRAINT PK_CaseForm PRIMARY KEY (CaseID, FormID)
);
CREATE TABLE CaseFormAttribute (
ID int NOT NULL PRIMARY KEY,
CaseID int NOT NULL FOREIGN KEY REFERENCES CaseForm (CaseID),
FormID int NOT NULL FOREIGN KEY REFERENCES CaseForm (FormID),
Name varchar(255) NOT NULL,
Value varchar(max)
);
CREATE TABLE Form (
ID int NOT NULL PRIMARY KEY,
FieldsJson varchar (max) NOT NULL
);
我是我过分复杂的架构,因为同样的多对多的关系可以通过转动CaseFormAttribute
表到连接表和获得完全摆脱CaseForm
表如下的实现?
CREATE TABLE CaseFormAttribute (
ID int NOT NULL PRIMARY KEY,
CaseID int NOT NULL FOREIGN KEY REFERENCES Case (ID),
FormID int NOT NULL FOREIGN KEY REFERENCES Form (ID),
Name varchar(255) NOT NULL,
Value varchar(max) NULL
);
基本上我想问的是哪个更好的设计?
答
拆分两者的主要好处取决于是否将其他字段添加到CaseForm表中。例如,假设你想记录表单是否不完整。您可以添加一个未完成位字段。现在,你有获取信息的主要选项:
- 聚集在CaseForm索引扫描
- 创建于CaseForm.Incomplete非聚集索引,其中包括CaseID,FormID,并扫描该
如果你没拆表,您的两个主要选项是:
-
上CaseFormAttribute
- 酶Cre
- 聚集索引扫描在包含CaseID,FormID和扫描的CaseFormAttribute.Incomplete上查找非聚集索引
对于本示例而言,查询选项1和2在性能方面大致相同。引入非聚集索引会以多种方式增加开销。它比聚集索引稍少一点(可能需要在此特定示例中扫描更多的读取),它是CaseForm将占用的额外存储空间,并且必须维护索引以更新表格。选项4也将执行类似的操作,但与选项2的警告相同。选项3将是您表现最差的执行者,因为聚簇索引扫描将包括读取“值”字段中的所有BLOB数据,即使它只需要“未完成”中的位以确定是否返回该(Case,Form)对。
所以它确实取决于你将来朝着什么方向发展。另外,如果您使用拆分方法,请考虑将CaseFormAttribute.ID转换为CaseForm,然后在CaseFormAttribute中将CaseForm.ID用作PK/FK。这里需要注意的是,我们假设所有的表单将被同时插入给定的案例。如果这不是真的,那么你会邀请一些页面拆分,因为你的插入会有点随机,但仍然会增加。
他们都会工作,但它取决于你需要什么表。你的ERD是什么样的? –
有没有比另一个更好的价值? – adam78
这取决于你是否需要caseform表或不,但我不能评论,因为我不知道你的数据库设计或要求 –