我怎么知道哪个是更合适的数据库设计? (作者、文章和评论)

How do I know which is the more appropriate database design? (Authors, Articles & Comments)

假设一个数据库包含三个表:AuthorArticlesComments

假设关系如下:

Author has many Articles
Article belongs to one Author
Article has many Comments
Comment belongs to one Article

如果我想知道哪个作者写的文章评论最多,我需要先 select 属于特定作者的所有文章。然后我可以计算在每篇文章下发表的评论数量。这通常会导致更复杂的查询。

如果关系如下:

Author has many Articles
Article belongs to one Author
Article has many Comments
Comment belongs to one Article
**Comment belongs to one Author of the relevant Article**

然后我可以直接 select 并计算在特定作者的文章下发布的所有评论,而无需在查询中包含这些文章。

但它暗示了一种冗余关系。

考虑到性能、可用​​性和编码最佳实践,哪种方法更好?

记得在什么地方看过,应该只用第一种方式,避免冗余关系。但我不记得在哪里或为什么。 link 回答这个问题的科学方法是什么?

"But I don't remember where or why? Please link to a scientific approach to answer this question."

"scientific approach"是归一化理论的全部。

"redundant relationship" 会在完整性实施方面造成额外的问题。系统必须确保更新数据库的用户指定的 comment/author 关系与 comment/article 和 article/author 关系隐含的关系相同。

这是一个在强制执行数据完整性时对系统造成额外复杂性的问题,对进行更新以确保他们不会指定无效更新的用户来说也是一个额外复杂性的问题。

因此,您的 "second approach" 可能确实会查询 "simpler",但代价是在 "updating" 方面增加了额外的复杂性。

您的第一种方法是规范化设计。它应该是默认的——它更易于维护,更不容易出错,并且总体上需要更少的代码。

第二个选项是非规范化设计。如果你想通了,每次有人发表评论,你都需要找到这篇文章的作者,并增加 "comments" 字段;那可能是更多的代码,并且使编写注释的速度变慢。这也意味着您 "create comment" 代码中的一个简单错误可能会破坏应用程序逻辑,您可能需要为每个评论 "write" 操作创建一个事务,以便您可以保证评论和更新 "authors.comment_count"成功或失败。

所以,第二个选项肯定更复杂,而且写评论更慢。它 可能 查询速度更快,但由于您将加入主键,您几乎肯定无法衡量性能影响,直到您的数据库大小达到数百数百万条记录。

总的来说,我推荐以下方法;只有在前面的步骤没有给您足够的性能时才采取每个步骤。

  • 设计一个关系模型。
  • 调整关系数据库(索引等)
  • 改进硬件 - RAM、CPU、SSD 磁盘等
  • 创建一个测量装置,以便您可以确定性能挑战和 运行 实验。根据当前和预期的数据大小创建基准;找到一种方法用虚拟数据填充您的测试平台,直到您拥有需要扩展的数据量。
  • 运行 您对测试平台的疑问。确保索引或查询优化没有进一步的性能调整。
  • 引入应用程序级缓存。在您的示例中,将作者的评论数缓存 1 小时可能是可以接受的。
  • 去规范化你的架构。使用您的测试装置来证明它可以提供您期望的性能。
  • 查看更奇特的数据解决方案 - 分片、数据分区等

非规范化之所以如此,是因为它引入了真正的维护风险,使您的代码 更加复杂,并且远不及向服务器添加额外的 4GB 那样有效在大多数情况下。

代表business/application关系(船)s/associations。正如在 关系 模型和实体-关系 建模中一样。每个查询结果都包含由查询表达式表达的某种业务关系相关的值行。

您的 "relationships" [原文如此] 是 FK(外键)。这些是约束条件——在每种业务情况及其数据库状态下都是正确的陈述——表示如果某些值与某种业务关系相关,那么它们也与另一种业务关系相关。但是 FK 对于使用数据库(解释或更新数据库)既不是必需的也不是充分的。他们限制 数据库状态,但不会告诉您其中的内容。

您的业务关系和相应的 table 实际上 像:

Author authored Article
Commenter commented Comment re Article

这样一个表示业务关系的语句模板就是它的(特征)谓词。要使用这些 约束是什么并不重要 -- 如果您希望作者对自己撰写的文章发表评论,那就是

/* rows where
FOR SOME a.* & cr.*,
        Author = a.Author
    AND a.Author authored a.Article
    AND cr.Commenter commented cr.Comment re cr.Article
    AND a.Author = cr.Commenter
*/
select Author
from authored a join commented_re cr on a.Author = cr.Commenter

不管一个作者是否可以创作多篇文章,或者多个作者可以创作一篇文章,还是多个作者可以创作多篇文章,或者评论者可以评论多条评论,等等,或者评论者可以评论多篇文章,等等,或者评论可以评论多篇文章,等等,或者作者可以评论,或者评论者可以创作,或者评论者只能评论他们创作的文章(FK 约束)或作者命名 'henk' 最多可以评论 7 篇文章,或者 任何限制

Normalization 将 table 替换为 selects join 回到它,这与说它替换了 a 相同其他人可以通过 AND 表达的业务关系,这些关系可以通过 ANDed 的表达来表达。恰好if一个作者只能写一篇文章,一篇文章只能由一个作者写then AND/join table 以上 可能 (取决于其他因素)是一个好的设计,否则 不是 是一个好的设计, 并且应该替换为单独的 tables。 FD 和其他约束是基于 post 设计 table 的相应业务规则的表达,这些规则遵循所选的业务关系以及可能出现的业务情况。

所以您的 "scientific approach" 是正确的关系信息建模和数据库设计,包括规范化。