传统的解决方案是连接表,类似于:
CREATE TABLE topicviews (
userid INTEGER NOT NULL,
topicid INTEGER NOT NULL,
lastread TIMESTAMP NOT NULL,
PRIMARY KEY (userid, topicid),
FOREIGN KEY (userid) REFERENCES users(id),
FOREIGN KEY (topicid) REFERENCES topics(id)
);
每次阅读主题时都会更新 lastread。显示主题列表时,如果topics.lastupdated > topicviews.lastread,则有新帖子。
传统的解决方案是垃圾,会杀死你的数据库!不要这样做!
第一个问题是,对每个主题视图的写入很快就会使数据库服务器在繁忙的论坛上陷入瘫痪,尤其是在只有表级锁的 MyISAM 表上。(不要使用 MyISAM 表,对除全文搜索之外的所有内容都使用 InnoDB)。
您可以稍微改善这种情况,只需在主题中实际读取新消息时写完 lastread 时间。如果 topic.lastupdated < topicviews.lastread 更新该值,您将一无所获。即便如此,在一个使用率很高的论坛上,这可能是一个负担。
第二个问题是组合爆炸。每个主题每个用户一行很快加起来:只有一千个用户和一千个主题,您可能有一百万个主题视图行要存储!
您可以通过限制为每个用户记住的主题数量来稍微改善这种情况。例如,您可以在视图表超过某个年龄时从视图表中删除任何主题,并假设所有旧主题都已“阅读”。这通常需要在后台完成清理任务。
其他不太密集的方法包括:
- 每个论坛只存储一个 lastread time
- 仅在整个站点中为每个用户存储一个 lastvisit 时间,这将显示为“新”仅自用户上次访问(会话)以来更新的内容
- 根本不存储任何 lastread 信息,但在主题的 URL 本身中包含最后更新时间。如果用户的浏览器最近看到过该主题,它会记住该 URL 并将其标记为已访问。然后,您可以使用 CSS 将访问的链接设置为“不包含新消息的主题”。