【问题标题】:How to structure database for unread item alerts per user如何为每个用户构建未读项目警报的数据库
【发布时间】:2012-06-12 18:06:37
【问题描述】:

我只是有一个一般的数据库理论问题。我需要做一些类似于显示用户查看或未查看的帖子/项目(例如在论坛中)或未读电子邮件的内容。我所拥有的是多个用户可以查看的帖子,但它需要由实际查看过的用户分开。因此,如果用户 A 查看了帖子 1,它将不再显示帖子 1 是要查看的新项目,但对于用户 B,它仍然会显示帖子 1 是要查看的新项目。

我已经搜索过其他想法,其中之一是获取用户上次登录时间的时间戳,但我实际上需要跟踪他们看到的帖子,而不是他们之后发生的帖子上次登录。

如果可能的话,我想要一个 MySQL 数据库解决方案,但如果这是必须的,我愿意接受 cookie。我可以自己做这件事并弄清楚,但我会很感激任何关于如何正确构建表格以使其最有效的建议。此外,带宽和存储也不是问题。

【问题讨论】:

  • 你可以看看 vBulletin 和其他论坛系统是如何处理它的,以获得一个想法。或者phpBB,因为我猜你必须购买 vBulletin。

标签: php mysql database-design cookies


【解决方案1】:

在查看relevant schema for phpBB时,我发现了以下内容:

# 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`;

还有:

# 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`;

那我look here in their wiki:

此表记录访问过的主题,以便将它们标记为 已读或未读。我们将 mark_time 时间戳与 主题 x 的时间戳的最后一篇文章,以了解主题 x 是否被读取。

为了准确判断一个主题是否被阅读,还必须 检查 phpbb_forums_track。

所以本质上他们有一个查找表来存储与用户查看主题(线程)相关的数据,然后将其与论坛视图表中的时间戳进行检查,以确定该主题是否已被用户查看.

【讨论】:

  • 这正是我所需要的。我将只创建 phpbb_forums_track 表,这应该可以完成我需要的工作。谢谢你
  • 没问题。我打算发布访问数据的查询的位置。如果我找到了,我会告诉你的。
  • 另外考虑你可能想要在服务器上的用户会话中缓存数据,所以你不断地调用那个查询(这可能很慢)。然后内置功能将视图数据推送到缓存,同时将其记录在数据库中。
  • @ImmortalFirefly - 这是为用户设置视图的部分:github.com/phpbb/phpbb3/blob/develop/phpBB/includes/…
【解决方案2】:

只需创建一个简单的交叉引用表(read_posts 或其他东西):

user_id|post_id
----------------
2      | 132
53     | 43
....

确保这两列都已编入索引(尤其重要的是 user_id 已编入索引),然后使用连接(或子查询)为已登录用户选择未读帖子。例如,如果您只是想显示未读帖子列表,则只需运行:

SELECT * FROM `posts` WHERE `post_id` NOT IN (
    SELECT `post_id` FROM `read_posts` WHERE `user_id`='[$USER ID]')
ORDER BY [your ordering clause]

【讨论】:

  • 子选择和IN 子句的性能对于诸如检查页面视图之类的事情会不会有问题?当然,除非在用户会话中对该数据进行前瞻性缓存。
  • 子查询的效率可能比连接低很多,但我认为在这种情况下子查询不会影响性能......复杂的子查询有时不会“选择”最有效的执行顺序,但我认为在这种情况下没有歧义,即使有大量行,性能也应该没问题——尤其是在正确使用索引的情况下。如果您有一些基准表明在这种情况下加入会更快,我会非常感兴趣。
  • 我相信你是对的。我仍然可能会使用JOIN,但这可能更偏好。无论如何,我认为最好的方法是在用户查看帖子/主题时结合使用会话缓存和双缓存/会话更新。这样查询实际上只在登录过程或会话设置期间运行,这将是高效且易于管理的。
  • 至少对于 phpBB 开发人员来说,看起来他们使用的是 JOIN:github.com/phpbb/phpbb3/blob/develop/phpBB/includes/…
  • 不要误会我的意思,出于同样的原因,我使用并且也经常喜欢子查询,而且我当然不是非凡的查询大师。我对IN 和子查询的看法是,需要充分理解它们才能在某些情况和应用程序中有效使用。因此,就查询结构而言,我看到了您所了解的内容,但并未表明可能导致执行时间不佳的问题。
【解决方案3】:

根据这个描述,我会使用一个可能有 3 列的简单表格。

  1. 用户 ID
  2. 帖子 ID
  3. 首次查看的时间戳

当用户查看帖子时,在表格中添加一行。如果给定用户/帖子 ID 组合的表中不存在一行,则他们没有查看该帖子。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-09
    • 1970-01-01
    • 2021-04-26
    • 2012-07-23
    • 2011-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多