派生概念 - 数据库设计考虑因素

时间:2011-05-23 18:04:56

标签: sql performance database-design normalization rdbms

我有一个主要概念 - 邮件消息和两个派生概念:

  • 模板生成的电子邮件
  • 自由格式的电子邮件

我正在考虑创建三个表来保存数据,我需要你对此事的看法(如果它很糟糕,如果它很好,如何改进等等):


MailMessages

  • Id [int] 身份(自动增量) PK
  • ToAddress [varchar(300)]
  • IsTemplateBased [bit]
  • TemplateId [int] nullable FK
  • MailBodyId [int] nullable FK (TemplateId必须为null且MailBodyId必须为非null,反之亦然)
  • StatusId [tinyint] FK

MailParams

  • MailMessageId [int] PFK
  • ParamNumber [tinyint]
  • 价值[nvarchar(4000)]

MailBody

  • MailMessageId [int] PFK
  • FromUsername [varchar(30)]
  • FromDomainId [tinyint] FK
  • PlainTextContent [nvarchar(max)]
  • HtmlContent [nvarchar(max)] nullable

这里有一些解释:

  • 我希望设计尽可能正常化
  • 可以省略IsTemplateBased位(布尔)列,并且可以从TemplateId和/或MailBodyId推断出邮件消息的性质(即:如果TemplateId不是null,那么它是基于模板的),但我认为这种去标准化(?)可能对性能有用
  • 有两列(FromUsername和FromDomainId)背后的原因是强制执行电子邮件健全规则 - 我不认为有一个列(FromAddress)是合适的

说完所有这些,亲爱的读者,你的意见是什么?

3 个答案:

答案 0 :(得分:1)

您可以简化并使其更像标准类型/子类型模型,如下所示:

  • 以MailMessags.Id作为“type”表主键
  • 开始
  • 将IsTemplateBased作为类型指示器,说明这是什么类型的电子邮件。 (我会把它变成一个tinyint,以便在将来可以用于索引和更多类型。)
  • 删除TemplateId和MailBodyId,您将不需要它们。
  • 在“子类型”表MailParams中,将MailMessageId设置为PK,并将FK设置为​​引用MailMessages.Id
  • 对MailBody.MailMessageId
  • 执行相同的操作

而不是三个不同的代理键(相应地更容易出错和混淆),现在只有一个可以管理。

答案 1 :(得分:1)

以下是@Philip Kelley注意到的“标准类型/子类型”模型示例:

type/subtype model

你有

  • SupertypeType。约束类型标识符域的域表。

  • 超类型。常见的超类型。对于其中一个子类型实例的每个实例,此表中都存在一行。它包含对象id(SupertypeID),对象类型标识符(TypeID)以及所有子类型中共有的属性。

  • 子类型。每个子类型都有一个表。它的主键是超类型表的对象id。对于超类型的每个实例,所有子类型表中不存在多于一行(当然,如果所讨论的实例是基本(超级)类型,则可能没有行。每个子类型表都有所不同,包含属性对于该特定子类别是唯一的。

要枚举所有元素,只查询超类型表。

如果您知道自己只对特定子类型感兴趣,则可以从相应的子类型表中选择,根据需要加入超类型表以获取所需的任何常用属性。

附录。如果您需要整个集合的平面非规范化视图,只需在子类型中保持联接:

select *
from Supertype     t
left join Subtype1 t1 on t1.SupertypeID = t.SupertypeID
left join Subtype2 t2 on t2.SupertypeID = t.SupertypeID
left join Subtype3 t3 on t3.SupertypeID = t.SupertypeID

现在您不需要多个查询。你已经交易了因为必须处理无效。

答案 2 :(得分:1)

您需要子类型模型,您还应该考虑消除这些空值所需的任何进一步分解。允许空值的表格不是普通表格。