哪个更好的数据库设计?
给定一个像StackOverflow这样的网站,创建num_comments列来存储提交的评论数量,然后在做出评论时更新它,或者只是使用COUNT函数查询行数,会更好吗?看起来后者更具可读性和优雅性,但前者效率更高。 SO认为什么?哪个更好的数据库设计?
绝对要使用COUNT。存储评论的数量是一个经典的去规范化,会产生令人头疼的问题。它的检索效率稍高一些,但是插入的代价要高得多:每个新的注释不仅需要插入到注释表中,而且需要在包含注释计数的行上写入锁。
这不是反规范化更多的优化,需要一些触发器 - 几乎不是头疼! – 2011-03-17 22:04:53
@JonBlack - 是的,这是一个优化(尽管如我在答案中所说的那样,“优化”是否值得不那么清楚)。同时,它绝对是一种反规范化。特别是,'num_comments'列违反了第三范式,因为它引入了非关键依赖关系 - 一个不依赖于关键字的值,但在这种情况下,这些关键值最可能来自完全不同的表。至于令人头痛的问题,这个问题不仅仅是写出“一些触发器”,而且随着数据库的发展,必须保持触发器以及其他一切。 – 2017-10-31 01:09:15
前者未规范化,但会产生更好的性能(假设读取次数多于写入次数)。
后者更规范化,但需要更多的资源,因此性能较差。
哪个更好归结为应用需求。
我会建议计数评论记录。虽然其他方法会更快,但它可以提供更清晰的数据库。添加计数列将是一种数据重复,更不用说额外的代码步骤和插入。
如果您希望获得数百万条评论,那么您可能需要选择count列方法。
我同意@Oded。这取决于应用程序的要求,也就是如何与现役的网站,但这里也是我的两分钱
- 我会尽量避免将不得不由触发器进行写操作,更新以新时评论张贴表被添加。
- 如果您担心报告数据,那么请勿在事务性系统上执行此操作。创建一个报告数据库并定期更新。
“正确的”设计方法是使用另一个表,加入它并COUNT
。这与database normalization教导的一致。
规范化的问题是它不能缩放。皮肤只有很多种方法来处理猫,所以如果你每天有数百万个查询,而且其中很多涉及到表X,那么数据库的性能会低于地面,因为服务器还必须处理并发写入,交易等。
要解决这个问题,一般的做法是sharding。分片具有副作用,表中的行不存储在相同的物理位置,并且主要的后果是您不能再JOIN
;你怎么能JOIN
对半桌,并收到有意义的结果?显然,尝试JOIN
针对表的所有分区并合并结果将比疾病更糟糕。
因此,您会发现,不仅您在实践中使用的替代方案可以实现高性能,而且还有更激进的步骤可供工程师采用。
当然,除非你做有性能问题,分片或甚至去规范化只是让你的生活更难以没有实际的好处。
这是如何将标度倾斜到包含num_comments列的? – 2011-03-17 21:37:14
如果SO需要连接表以显示注释计数,则它不会存在。但是,担心当你的网站每天被数百万的综合浏览量击中时会发生什么,我们只是说,不成熟 - 所以在你自己的项目中,使用“COUNT”。 – Jon 2011-03-17 21:01:01
不要过早优化。保持数据库规范化,直到你需要对它们进行非规范化。 – Quentin 2011-03-17 21:02:51
@Jon:有趣......你能详细说明还是提供链接?我在关系模型之外坚果,但总是准备学习... – 2011-03-17 21:03:58