php - 使用 php 和 mysql 为简单论坛设计的高效数据库

标签 php mysql database optimization

我正在为我的网站设计用于论坛功能的数据库。在 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/

相关文章:

java - 如何使用 WSDL

php - 使用 PHP/JAVA 从 MySql 数据库获取数据到 PDF 表单

php - 如何在网页上仅显示数据库中已发布的 ACTIVE 博客?

Mysql:允许Null的意思

database - 如何以简单的方式删除选定的 100 个临时数据库

php - JavaScript 中的正则表达式搜索

php - 为什么 apache 将偏移量保存到 php-cli 保存虚拟内存地址的内存中?

php遍历数组中的对象数组

mysql - ZF2 服务未找到数据库适配器

python - 如何避免将重复项插入数据库的最有效方法?