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

时间:2017-04-26 23:37:20

标签: database database-design relational-database database-normalization

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

假设关系如下:

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

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

如果关系如下:

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**

然后我可以直接选择和统计在特定作者的文章下发布的所有评论,而无需在查询中包含文章。

但这意味着多余的关系。

鉴于性能,可用性和编码最佳实践,哪种方法更好?

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

3 个答案:

答案 0 :(得分:4)

“但我不记得在哪里或为什么?请链接到一个科学的方法来回答这个问题。”

“科学方法”是整个规范化理论的主体。

“冗余关系”在完整性实施中产生了额外的问题。系统必须确保更新数据库的用户指定的注释/作者关系与注释/文章和文章/作者关系所暗示的相同。

在执行数据完整性时,这是系统额外复杂性的问题,并且对于进行更新的用户而言是一个额外复杂性的问题,以确保他们不会指定无效更新。

所以你的“第二种方法”可能会使查询变得“更简单”,但这只会导致在“更新”方面产生额外的复杂性。

答案 1 :(得分:1)

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

第二种选择是非规范化设计。如果您仔细考虑,每次有人发表评论时都需要您找到文章的作者,并增加“评论”字段;这可能是更多的代码,并使写评论更慢。这也意味着“创建注释”代码中的一个简单错误可能会破坏应用程序逻辑,您可能需要为每个注释“写入”操作创建一个事务,这样您就可以保证注释和更新到“authors.comment_count”成功还是失败。

因此,第二个选项肯定更复杂,写评论的速度更慢。 可能查询速度更快,但是当您加入主键时,几乎肯定无法衡量性能影响,直到达到数亿条记录的数据库大小为止

总的来说,我推荐以下方法;只有在前面的步骤没有给你足够的表现时才采取每一步。

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

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

答案 2 :(得分:1)

表示业务/应用程序关系(发货)/协会。与关系模型和&amp; entity- relationship 建模。每个查询结果都包含由查询表达式表示的某些业务关系相关的值行。

您的“关系”[原文如此]是FK(外键)。这些都是限制因素 - 在每种商业情况下都是如此。它的数据库状态 - 如果某些值与某个业务关系相关,那么它们也与某个其他值相关。但是FK对于使用数据库来说既不必要也不充分 - 用于解释或更新数据库。他们约束数据库状态,但他们没有告诉你它的内容。

您的业务关系&amp;相应的表实际之类:

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'可以评论re最多7篇文章,或任何约束

规范化selects的{​​{1}}替换为join表,这与表示它取代可通过{{{{}表达的业务关系相同。 1}}由AND ed表达式表达的其他人。碰巧是如果作者只能写一篇文章而且一篇文章只能由一位作者然后上面的AND / AND表编写可能(取决于其他事情)是一个好的设计,但否则是一个好的设计,应该由单独的表替换。 FDs&amp;其他约束是从所选择的业务关系中得到的相应业务规则的基于设计后表格的表达。可能出现什么样的商业情况。

所以你的“科学方法”是适当的关系信息建模和数据库设计,包括规范化。