好的,在50号公路上又是一个有趣的问题。
我们希望实现一个真正的论坛灯泡系统,其中用户未读的帖子(在用户的帐户创建之后)显示为未读,直到该状态被清除或用户读取它们为止。
我们认为最好和最简单的方法是实现未读消息表。
列是:user_id
,board_id
,thread_id
,post_id
,timestamp
和hidden
这对于查看每个用户未读(并链接到它们)的哪些板/线程/帖子非常有效且非常快,但是即使只有一个SQL查询,用户发布到论坛的速度也很慢正在运行:
INSERT IGNORE INTO `forums_lightbulb` SELECT `id`,'x','x','x',UNIX_TIMESTAMP(),0 FROM `users`
我确定这是拥有3065个用户帐户的结果。我怎样才能加快这个过程?我宁愿让系统保持尽可能实时。
重要提示:请将您的答案限制在共享托管环境中,无需额外预算。我们仅限于PHP和MySQL 5.1.53-log
答案 0 :(得分:10)
PHPBB做的是一种非常快速的方法。它保留了一个表,用于标记每个线程和每个论坛的最后一次是用户打开它的时间。并使用它来确定是否有未读消息。它允许用户*主题+用户*论坛存储使用方案,同时允许使用非常简单和快速的查询进行检查。
您可以从数据库结构中看到它的工作原理。
# Table: 'phpbb_forums_track'
CREATE TABLE phpbb_forums_track (
user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
mark_time int(11) UNSIGNED DEFAULT '0' NOT NULL,
PRIMARY KEY (user_id, forum_id)
) CHARACTER SET `utf8` COLLATE `utf8_bin`;
# Table: 'phpbb_topics_track'
CREATE TABLE phpbb_topics_track (
user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
mark_time int(11) UNSIGNED DEFAULT '0' NOT NULL,
PRIMARY KEY (user_id, topic_id),
KEY topic_id (topic_id),
KEY forum_id (forum_id)
) CHARACTER SET `utf8` COLLATE `utf8_bin`;
答案 1 :(得分:4)
很抱歉,但问题中提出的解决方案是不可扩展的设计。
我在here上调查了这个问题,对它进行了不错的讨论(在我出现之前)。看看那里。
在您的情况下,存储U * M记录以跟踪“未读”帖子,其中U是用户数,M是消息数,将非常非常快速地失控。这是因为它的最佳效率需要所有用户阅读每条消息(大多数用户并不关心所有内容,因为论坛上的大多数内容都是噪音)。平均情况下,可能有20%的用户已经阅读了100%的帖子,但80%的用户已经阅读了近0%的帖子,从未阅读过其余的帖子。这意味着您被迫存储0.8 * U * M,而U和M仅在几何上增加。没有多少索引可以解决这个问题。
之前的@ will-hartung答案具有更高效的方法。
我发现这已经很老了,我希望你能在此期间找到更好的解决方案。
答案 2 :(得分:2)
这是最有效的方式:
read_threads
的表,用于存储thread_id
和user_id
users
表中有一个名为mark_read_date
的列,用于存储用户点击论坛中mark all threads read
链接的日期read_threads
表中,或者它的last_post_date
(最后一个帖子的日期)是否更早而不是users
mark_read_date
当用户点击论坛中的read_threads
链接时,同时删除mark all threads read
表格中的所有行也很重要。
答案 3 :(得分:1)
阅读:
insert into read_articles(user_id, article_id);
显示:
SELECT a.*, r.user_id FROM articles a
LEFT OUTER JOIN read_articles r ON (a.article_id = r.article_id and r.user_id = $user_id)
WHERE (article_filter, like forum or thread id, or whatever)
在结果集上,如果user_id不为null,则他们已阅读该文章。否则,他们没有。
适当的索引。服务员用饼干和果酱加热。