【问题标题】:Which is better database design?哪个数据库设计更好?
【发布时间】:2011-07-17 17:45:44
【问题描述】:

给定一个像 * 这样的网站,创建 num_cmets 列来存储提交有多少 cmets,然后在发表评论时更新它,还是只使用 COUNT 函数查询行数会更好吗?似乎后者更具可读性和优雅,但前者会更有效。 SO怎么想的?

【问题讨论】:

  • 如果 SO 需要加入表格以显示评论计数,它就不会存在。但是,当您的网站每天受到数百万次网页浏览量的影响时,担心会发生什么,让我们说,为时过早——所以在您自己的项目中,请使用COUNT
  • 不要过早优化。保持数据库规范化,直到您需要对它们进行非规范化。
  • @Jon:有趣...您能详细说明或提供链接吗?我在关系模型之外很疯狂,但随时准备学习......
  • @iDevlop:提交了答案,看看。

标签: php mysql sql database-design


【解决方案1】:

一定要使用 COUNT。存储 cmets 的数量是一种经典的反规范化,会让人头疼。检索效率稍高,但插入成本更高:每个新评论不仅需要插入 cmets 表,还需要对包含评论计数的行进行写锁定。

【讨论】:

  • 它不是非规范化,而是一种优化,需要一些触发器 - 几乎不让人头疼!
  • @JonBlack - 是的,这是一种优化(尽管正如我在回答中所说,“优化”是否值得并不清楚)。同时,它绝对是一种非规范化。具体来说,num_comments 列违反了第三范式,因为它引入了非键依赖——一个不依赖于键的值,但在这种情况下,值很可能来自完全不同的表。至于令人头疼的问题,问题不仅仅是编写“一些触发器”,而且随着数据库的发展,还必须维护触发器以及其他所有内容。
【解决方案2】:

前者未标准化,但会产生更好的性能(假设读取次数多于写入次数)。

后者更加规范化,但需要更多资源,因此性能较低。

哪个更好归结为应用程序要求。

【讨论】:

    【解决方案3】:

    我建议计算评论记录。尽管另一种方法会更快,但它可以提供更清洁的数据库。添加计数列将是一种数据重复,更不用说需要额外的代码步骤和插入。

    如果您期望数百万个 cmets,那么您可能希望选择计数列方法。

    【讨论】:

      【解决方案4】:

      我同意@Oded。这取决于应用程序的要求以及网站的活跃程度,但这也是我的两分钱

      • 我会尽量避免必须由触发器完成的写入操作,在添加新 cmets 时更新发布表。
      • 如果您担心报告数据,请不要在事务系统上这样做。创建报告数据库并定期更新。

      【讨论】:

        【解决方案5】:

        “正确”的设计方法是使用另一个表,加入它和COUNT。这与database normalization 所教导的一致。

        规范化的问题在于它无法扩展。剥猫皮的方法只有这么多,所以如果你每天有数百万个查询并且其中很多都涉及到表 X,那么数据库性能就会下降,因为服务器还必须处理并发写入、事务等.

        为了处理这个问题,一个常见的做法是sharding。分片的副作用是表的行不会存储在相同的物理位置,其主要后果是您不能再JOIN;您如何JOIN 对抗半张桌子并获得有意义的结果?显然,尝试JOIN 对表的所有分区并合并结果将比疾病更糟。

        因此,您看到不仅您检查的替代方案在实践中用于实现高性能,而且工程师可以而且确实采取了更激进的步骤。

        当然,除非您确实遇到性能问题,否则分片甚至反规范化只会让您的生活变得更加困难而没有任何实际好处。

        【讨论】:

        • 这如何使天平向包括 num_cmets 列倾斜?