2

对不起,如果标题有点......蹩脚。基本上我在写一个小论坛,使用多个子查询来选择论坛的线程数,帖子数,最后一次帖子的日期,同时抓取论坛的信息显示在主页上!

这是我的疑问,因为我不擅长解释事情:

SELECT `f`.*,
    (SELECT COUNT(`id`)
    FROM `forum_threads` 
    WHERE `forumId1` = `f`.`id1`
        AND `forumId2` = `f`.`id2`) AS `threadCount`,
    (SELECT COUNT(`id`)
    FROM `forum_posts` 
    WHERE `forumId1` = `f`.`id1`
        AND `forumId2` = `f`.`id2`) AS `postCount`,
    (SELECT `date`
    FROM `forum_posts` 
    WHERE `forumId1` = `f`.`id1` 
        AND `forumId2` = `f`.`id2` 
        ORDER BY `date` DESC LIMIT 1) AS `lastPostDate`
FROM `forum_forums` AS `f`
ORDER BY `f`.`position` ASC, `f`.`id1` ASC;

并且正在使用一般的 foreach 循环来显示结果:

foreach($forums AS $forum) {
    echo $forum->name .'<br />';
    echo $forum->threadCount .'<br />';
    echo $forum->postCount .'<br />';
    echo $forum->lastPostDate .'<br />';
}

(当然不完全一样,但为了解释......)

现在我想知道这是否对性能“不利”,或者是否有更好的方法?假设每个论坛中有很多帖子和主题。

我最初在论坛表本身中存储“posts”、“threads”和“lastPost”列,并且每次有人创建新线程或帖子时都会增加(posts = posts + 1)值。虽然我也有这个想法,并且想知道它是否有什么好处。:P

4

2 回答 2

2

我会做一些不同的事情:

在我看来,所有这三个字段:threadCountpostCount都是lastPostDate您可以在单独的表中维护的字段,例如forum_stats仅包含 4 列:
* forum_id
* thread_count
* post_count
* last_post_date

这些列可以通过更新。在插入/更新时触发。
如果您在更新操作期间支付这么小的开销 - 您将获得非常快速的查询select(无论您拥有多少论坛/帖子/线程,它都会保持非常快)。

另一种方法(不是我们好的 TMO):
创建统计表并每天(或每隔几个小时)运行一个批处理作业,它将更新统计信息。代价是您显示的数据永远不会是最新的,并且该作业可能需要资源,例如,您可能只想在晚上运行该作业,因为它很重并且您不希望它生效大多数网站访问者。

于 2012-08-29T05:52:42.363 回答
1

通常这种事情从性能的角度来看是很糟糕的,最好使用可以从单行获取的计数器列。保持这些同步可能很烦人,但是一旦它们在那里就没有检索成本。

您已经确定了要检索的数据,所以接下来您需要首先弄清楚如何将这些数据放入其中。@alfasin 的回答描述了一个示例模式,虽然将其放在单独的表中是一种想法,但通常不会有太多麻烦,只需将它们放在主表中即可。如果您担心锁定,请小批量更新。

一种方法是编写一个TRIGGER在从各种表中添加和删除记录时更新计数器的方法。这往往会隐藏很多复杂性,如果逻辑经常更改并且人们需要了解系统的工作方式,这可能是一件坏事。

一种简单的方法是在创建或删除会更新它们的内容后,使用附加查询来处理列。例如,如果您在创建帖子时进行调整,那么调整最后发布日期是微不足道的。

如果这些计数器有点乱,而且它们最终会出现问题,那么您需要一种方法让它们重新同步。一种简单的方法是编写一个VIEW产生与您现在的查询相同的结果的方法,也许重新编写以LEFT JOIN代替使用,然后UPDATE在可能的情况下反对它。如果 MySQL 无法处理更新具有自身视图的表,这可能涉及使用临时表,但这通常不是什么大问题。

于 2012-08-29T06:07:02.570 回答