创建论坛软件-寻找最好的方式去做一件事


Creating forum software - looking for the best way to go about 1 thing

好吧,我喜欢用PHP和MySQL制作论坛软件,尽管有一件事一直困扰着我,而且只有一件事;

论坛的主页面,在这里您可以查看论坛列表。每个论坛都会显示论坛名称、该论坛的帖子数量、该论坛的讨论数量以及该论坛的最后一位发帖者。问题就在这里,当所有这些数据都存储在不同的表中时,获取所有这些数据。GET It不是什么大问题,根本不是什么大问题,但我所追求的是高效地完成它。

我目前的方法是这样的;将当前帖子、讨论和最后一个帖子的数量静态地存储在论坛表中,而不是从不同的表("posts"、"discussion"、"forums"等)中抓取数据。然后,当用户发帖时,它更新"论坛"表,将帖子数量增加1并更新最后一个发帖者,如果他们正在进行新的讨论,也将讨论数量增加1。出于某种原因,这对我来说似乎既低效又肮脏,但也许只是我的问题。

还有另一种方法,我担心效率会非常低;实际上,我要去每一张桌子上——"帖子"、"讨论"、"论坛"——获取数据。问题是,一个页面上可能有数百个论坛……我必须使用COUNT语句来获取帖子或讨论的数量,这意味着我必须使用子查询—更不用说第三个子查询来获取最后一个帖子。话虽如此……查询应该是类似于下面这种伪代码的东西:

SELECT foruminfo, (
    SELECT COUNT(id)
    FROM posts
    WHERE forumId = someid
), (
    SELECT COUNT(id)
    FROM discussions
    WHERE forumId = someid
), (
    SELECT postinfo
    FROM posts
    WHERE forumId = someid
    ORDER BY postdate
    DESC LIMIT 1
)
FROM forums
ORDER BY position DESC;
所以基本上那些子查询可以运行数百次,如果我有数百个论坛被列出。每秒钟都有数以百计的用户浏览这个页面,这难道不会造成相当大的压力吗?我不完全确定子查询是否会导致与普通查询相同数量的负载,但如果确实如此,那么它似乎肯定会非常低效。

任何想法?(

我以前建立过一个大型论坛系统,使其性能良好的关键是将任何东西都去规范化。

您不可能在真正流行的页面上实际使用JOIN。您必须将发出的查询数量保持在绝对的最低限度。永远不要使用子选择。始终确保您的索引涵盖了确切的用例,而不是更多。运行时间超过1-5ms的查询对于大规模运行的站点来说可能太慢了。当由于严重的负载,突然需要十倍的时间来运行一个15毫秒的查询将花费150毫秒或更多的时间,而优化后的1毫秒查询将花费10毫秒。你的目标是让它们一直是0.00,这是可能的。

请记住,当你执行查询并等待响应时,你不能做任何其他事情。如果你稍微不小心,请求来的速度就会超过你处理它们的速度,整个系统就会崩溃。

保持你的模式简单,甚至是愚蠢的简单,我的意思是考虑你的页面布局,你要显示的信息,并使模式尽可能准确地匹配。只留下最基本的东西。以尽可能接近最终输出的格式表示它,而不做不必要的妥协。

如果你显示用户名,头像,帖子标题,帖子数量,发布日期,那么这就是你在数据库中的字段。是的,你仍然会有一个单独的用户数据库,但是把所有的东西都转换成一个直接的结构,使它像这样简单:

SELECT id, username, user_avatar, post_title, post_count, post_time FROM posts
  WHERE forum_id=?
  ORDER BY id DESC

通常情况下,您必须加入对抗users以获得他们的名字,也许另一个表以获得他们的特定头像,以及讨论表以获得帖子计数。您可以通过更改存储策略来避免这一切。

在我工作的情况下,它是一个要求,能够在未来以及过去发布的东西,所以我不得不创建一个特定的"排序键"独立于ID,像你的position。如果不是这种情况,只需使用id主键进行排序,如下所示:

INDEX post_order (forum_id, id)

使用SUMCOUNT是完全不可能的。你需要反缓存列。这些东西可以保存特定论坛中有多少消息的计数。是的,它们会像任何非规范化数据一样偶尔偏离同步,因此您需要添加工具来检查它们,并在需要时完全重建它们。通常,您可以将其作为每天运行一次的临时作业来修复可能发生的任何轻微损坏。大多数情况下,如果你的实现是正确的,它们将完全同步。

其他需要注意的事情,如果可以的话,将帖子分成几个线程。你的桌子越小,速度就越快。筛选所有帖子以找到每个线程的顶级帖子非常慢,特别是在流行的系统上。

同时,缓存任何你可以在Memcached之类的东西,如果这是一个选项。例如,除非添加或删除一个朋友,否则用户的朋友列表不会改变,因此您不需要经常从数据库中选择该列表。最快的数据库查询是你从来没有做过的,对吧?

要正确地做到这一点,你需要知道每一页的布局和上面的信息。不太受欢迎的页面需要较少的优化,但主线中的任何内容都必须仔细检查。像许多事情一样,可能存在80/20规则,即80%的流量只访问20%的代码库。