我正在为我的网站设计用于论坛功能的数据库。在 SO 和谷歌上进行一些搜索后,我提出了以下设计: 用户表
Username : varchar(256)
Password : varchar(256)
线程表
ThreadId : int
UserId : int, related to Users table
Title : varchar(255)
Date : timestamp, when a thread was created
帖子表
PostId : int
ThreadId : int, related to Threads table
UserId : int, related to Users table
Date : timestamp, when post was made
Title : varchar(255) - post title (optional)
Body : text - the actual body of a post
尽管这符合我的目的,但我不禁认为这不是很有效,尤其是对于为特定线程选择所有帖子时,需要遍历整个表。
从我的脑海中,我可以想到一种设计,其中 Users 表 和 Threads 表 保持原样,但没有一个表用于Posts 表,我为每个与用户同名的用户创建了一个Posts 表。这样检索属于一个线程的所有帖子效率更高,因为我只需要启动线程的人的用户 ID。使用此信息,我搜索具有相同名称的表以检索特定线程的所有帖子。但是直接创建表的数量是个好主意吗取决于注册用户的数量?我还想知道的是,这些设计中的哪一个扩展性更好,更易于管理?是否有更好的数据库设计来满足我的要求?
最佳答案
你的设计看起来基本上是正确的。
这是一个经典的“规范化” 数据结构 - 正是关系数据库构建的那种形状。如果您不了解范式,但想到了这种结构,那么您显然对关系数据库的工作原理有了自然的理解。
http://en.wikipedia.org/wiki/Database_normalization#Normal_forms
为了让 PHP 避免遍历整个表,您应该确保您发出的 SQL 语句只选择您要查找的记录。例如
SELECT * FROM posts WHERE ThreadId = ? ORDER BY Date
您担心数据库必须遍历整个表是公平合理的,尽管您可以避免这种情况 - 这是一个经典的关系数据库问题,30 多年前它们首次作为商业产品出现时就已经解决了。
您可以在帖子上创建一个索引,以支持您正在运行的 SQL。在这种情况下,类似于以下内容:
CREATE INDEX postThreadsIndex ON posts ( ThreadId, Date )
此索引允许您的数据库引擎非常快速地找到您选择的记录,而无需读取整个表。如果您想知道如何操作,请阅读 B 树索引。
http://en.wikipedia.org/wiki/B-tree
正如我之前在回答中所说,这正是构建关系数据库的目的,您的设计是可靠且恰当的。
不要考虑任何替代方案 - 您一次就做对了!
但是,为了完成 - 让我们看看您建议的替代方案。
您建议按用户拆分 Post 表 - 这意味着以下内容:
- 用户“UserA”创建了一个话题——他的初始帖子存储在 posts_UserA 中
- 用户“UserB”回复帖子 - 他的帖子在 posts_UserB 中有故事
- 用户“UserC”回复了帖子 - 她的帖子在 posts_UserC 中有故事
为了检索完整的线程,您现在需要查看 posts_UserA、posts_UserB 和 posts_UserC。
如果只有这三个用户,那么您需要查看这三个表中的所有数据才能找到所有帖子,这将等于将 已出现在您的原始设计中的表格帖子中。
你一无所获。
如果您有 1000 个其他用户,您还必须查看其他 1000 个表才能发现他们没有任何记录。
你还是一无所获。
您可以添加另一个表来存储哪些用户对哪些帖子发表了评论 - 因此要查看哪些表,但现在解决方案开始变得复杂。
您可以按线程拆分帖子表 - 这意味着表格中的所有帖子都基于它们的创建线程。这对于在单个线程上选择帖子可能非常好,但对于以下情况来说就很糟糕了: - 选择给定用户发布的所有帖子。 - 无论线程如何,都能找到最新的帖子。 - 查找在特定日期发布的所有帖子。 - 不涉及特定线程的任何其他内容。
基本上,您建议的备选方案可能对于非常特定的查询更有效,但对于任何其他查询几乎总是极其复杂。
原始设计对于所有查询来说都比较简单,可以通过添加索引使其性能良好。
如果您曾经因为数据量而达到 SQL 性能太慢的地步,那么您可以查看表分区,它以不可见的方式执行您描述的操作。但老实说,除非您的网站非常受欢迎,否则您不太可能需要它 - 如果是这种情况,那么您可能有足够的现金来投资关系数据库基础类(class)......
关于php - 使用 php 和 mysql 为简单论坛设计的高效数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20017113/