我正在使用php创建一个论坛应用,并对数据库设计有疑问:
我可以获取特定主题的所有帖子。所有帖子都有auto_increment标识列以及时间戳。
假设我想知道主题启动者是谁,哪个是最佳解决方案?
按时间戳获取主题和订单的所有帖子。但是,如果有人立即回复该主题会发生什么。然后我有前两个帖子具有相同的时间戳(不太可能,但可能)。我不知道第一个是谁。这也是标准化的,但在表增长后变得昂贵。
通过post_id获取主题和订单的所有帖子。这是一个auto_increment列。我可以保证数据库将按插入顺序使用索引ID吗?稍后插入的帖子是否会比以前的行具有更高的ID?如果我删除帖子怎么办?我的数据库以后会重用post_id吗?这是我正在使用的mysql。
最简单的方法是简单地使用topic_starter_id将一个字段添加到Topics表中并完成它。但它没有正常化。我相信这也是主题和帖子表增长到数百万行之后最有效的方法。
您有什么看法?
答案 0 :(得分:3)
Zed的评论非常有用。
您通常希望实现规范化,但非规范化可以节省潜在的昂贵查询。
根据我编写论坛软件的经验(商业五年,作为业余爱好五年),这个特殊情况需要非规范化来保存单个查询。存储第一个用户的显示名称和ID以及最后一个用户的显示名称和ID是完全理智和可接受的,只要将帖子添加到主题的代码总是更新记录即可。。你想要一个且只有一个代码路径。
答案 1 :(得分:0)
我必须在某种程度上不同意Charles,因为节省性能的唯一方法是去标准化以避免额外的查询。
更具体地说,有一种优化可以在没有非规范化的情况下工作(以及随之而来的数据维护/完整性问题),但只有当用户群足够小时(假设为了论证,我们说< 1000个用户)取决于你的规模。我们的应用程序使用这种方法与10k +映射。)
即,您拥有应用程序层(在Web服务器上运行的代码),将用户列表检索到适当的缓存中(例如,具有数据到期设施)。然后,当您需要打印第一个/最后一个用户的名字时,请在服务器端的缓存中查找。
这避免了对每个页面视图的额外查询(因为您需要仅在每N页面视图中检索完整用户列表ONCE,当缓存过期或更新用户数据时应导致缓存过期)。
它在Web服务器上增加了一点CPU时间和内存使用量,但在又一个神圣战争中(例如在DB端或app服务器端花费更多资源)我坚定地“不要浪费数据库资源” “看看如何扩展数据库比扩展网络或应用服务器要困难得多。
是的,如果那个(或其他同样棘手的)优化不可行,我同意Charles和Zed你在规范化(与数据完整性相关的麻烦较少)和性能提升之间进行权衡(少一个表到加入一些查询)。由于我在那场特殊的圣战中不可知,我只是选择了更好的边际效益(例如,性能损失多少与去标准化的成本/风险有多少)