哪种数据库设计更好?

7

假设有一个像StackOverflow这样的网站,是创建一个num_comments列来存储提交的评论数量,然后在每次发表评论时更新它还是只使用COUNT函数查询有多少行更好呢?使用COUNT函数似乎更易读和优雅,但使用前者更有效率。SO网站认为什么?


1
如果 Stack Overflow 需要联接表格来显示评论计数,那么它就不存在了。但是担心当您的网站每天被数百万次页面访问时会发生什么,这只能说是过早的——因此在您自己的项目中,请使用 COUNT - Jon
5
不要过早优化。保持数据库规范化,直到需要去规范化为止。 - Quentin
1
@Jon:有趣...你能详细说明或提供链接吗?我对关系模型之外的东西感到困惑,但我总是愿意学习... - iDevlop
@iDevlop:已提交答案,请查看。 - Jon
5个回答

8

使用COUNT函数是明智的选择。储存评论数量是一种经典的反规范化方式,但会带来很多麻烦。虽然这种方法检索效率稍高,但插入操作变得更加昂贵:每次新增评论不仅需要插入到评论表中,还需要对包含评论计数的行进行写锁定。


1
这不是反规范化,更多的是一种优化,只需要一些触发器 - 几乎不会带来麻烦! - Jon Black
@JonBlack - 是的,这是一种优化(尽管,如我在答案中所说,“优化”是否值得并不太清楚)。与此同时,它绝对是一种非规范化。具体来说,一个 num_comments 列违反了第三范式,因为它引入了一个非键依赖关系 -- 一个与键无关的值,但在本例中依赖于很可能来自完全不同表格的值。至于头痛问题,问题不仅仅是编写“几个触发器”,而且还要随着数据库的演变来维护触发器以及其他所有内容。 - Ted Hopp

3

前者没有被规范化,但会产生更好的性能(假设读操作远多于写操作)。

后者被规范化得更好,但需要更多资源,因此性能较差。

哪种更好取决于应用要求。


2
我建议计算评论记录。虽然另一种方法更快,但它会使数据库更清洁。添加一个计数列将是一种数据复制,更不用说需要额外的代码步骤和插入了。如果您预计有数百万条评论,那么您可能希望选择计数列方法。

2

我同意@Oded的观点。这取决于应用程序的要求以及网站的活跃程度,但是以下也是我的建议:

  • 尽量避免使用触发器进行写入操作,例如在添加新评论时更新帖子表。
  • 如果您担心数据报告,则不要在事务性系统上执行此操作。创建一个报告数据库并定期更新该数据库。

2
“正确”的设计方式是使用另一个表进行连接和 COUNT。这与数据库规范化所教授的一致。
规范化的问题在于它不能扩展。有很多种方法可以解决问题,因此如果您每天有数百万个查询并且其中许多涉及到表 X,则数据库性能将下降,因为服务器还必须处理并发写入、事务等。
为了解决这个问题,一个常见的做法是分片。分片的副作用是表的行不会存储在同一个物理位置上,这个主要的后果是您不能再进行 JOIN 了;您如何对半个表进行 JOIN 并获得有意义的结果呢?显然,尝试对表的所有分区进行 JOIN 并合并结果比病情更糟糕。
因此,您可以看到,不仅您所考虑的替代方案被用于实现高性能,而且工程师们还可以采取更激进的步骤。
当然,除非您有性能问题,否则分片甚至去规范化只会让您的生活更加困难,没有实际的好处。

这会如何倾向于包括 num_comments 列? - Ted Hopp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接