【问题标题】:How to optimize count of new posts in favorites如何优化收藏夹中新帖子的数量
【发布时间】:2011-03-10 17:41:35
【问题描述】:

我想说,我会很高兴收到任何回复。我将尝试组织我的文本以便更好地理解。

情况 我运行主题互联网论坛,您可以在其中将主题添加为菜单中的收藏夹,菜单显示这些主题中的新帖子数量。因此,每次您重新加载页面(转到整个网站的任何位置)时,都会检查您收藏夹中所有主题的新帖子。

问题 这在 DB 上当然是相当昂贵的,因为通常有 20-50 个收藏夹,如果在这些主题中添加了任何帖子,我必须检查 DB。平均主题有 1000-2000 个帖子。每个用户的每次浏览量都会发生这种情况,每月浏览量约为 900 000 次。

可能的解决方案 1 我存储每个主题中的帖子总数,并为每个用户存储每个主题的最后查看帖子的数量。这可能是最快的,但它有很多缺点,它们是功能性的(删除、过滤帖子等)。

可能的解决方案 2 我为每个用户存储每个主题的最后查看帖子的 ID。这是一个很好的解决方案,但比之前的解决方案慢了十倍左右。

数据库 我将所有主题的所有帖子存储在一个巨大的表格中 = 数十万个帖子。

问题 我想消除带来解决方案 1 的问题,但我需要保持速度。我想为每个主题创建一个表格并使用解决方案 2,但我不知道它是否会有所帮助。因此,如果您有任何经验,请告诉我最快的解决方案是什么。

非常感谢。

【问题讨论】:

    标签: sql optimization bookmarks favorites


    【解决方案1】:

    Firsty:不知道您的架构或数据库系统,但这应该相对简单,假设您记录了您的用户最后一次出现的时间(下面示例中的 $DATE_USER_WAS_LAST_SEEN)并且您的每个帖子都可能与它相关联通过某种 id 的主题,你有一个所有 $FAVOURITE id 的列表。

    SELECT topic_id, count(*) AS count FROM posts 
    WHERE topic_id IN ($FAVOURITES) 
        AND created_date > $DATE_USER_WAS_LAST_SEEN 
    GROUP BY topic_id
    

    会给你这样的输出:

    topic_id   |   count
    ---------------------
      3        |     20
      1        |     27
      33       |     120
    

    对于这种规模来说,这应该是可以接受的速度,如果您的数据库没有自动优化这些东西,您可以不使用IN 并制作一个长的(topic_id = 1 OR topic_id = 2 OR topic_id = etc) 字符串来改进查询。

    其次:不要太担心这些值是否及时更新。人们会将它们用作有新消息的指示器,而不是基于它们的生活决策,因此请为每个用户缓存这些请求(在用户自己的记录中或使用某种内存缓存,如 memcache,如果您熟悉这些) ) 并每隔 5 分钟左右过期一次缓存,这将大大减少您对数据库的访问量

    【讨论】:

    • 嗨,谢谢。这给我带来了一个想法。此解决方案与 id 解决方案基本相同,但我意识到,在测试之前我没有重新访问所有收藏夹,所以我在每个收藏夹中都有大约 1000 个新帖子,这可能会导致缓慢。可以肯定的是,还有一个问题。当我只有 10 个新帖子时,count(id) 会更快吗?
    • 这两种解决方案的问题在于,它们要求您在每次查看后写入 到数据库。写入慢,读取快。因此,通过估计您最后一次看到用户并使用它来计算自他们上次访问以来的帖子数量,您可以节省大量对数据库的写入。如果您为 created_date 和 topic_id 设置索引,count() 将尽可能快。通过使用组,您可以节省向数据库发出多个请求的开销。
    【解决方案2】:

    我想你的帖子 ID 是连续的并且总是递增的。

    为您的最爱创建一个至少包含以下字段的表格:user_id、topic_id、last_post_id

    然后您可以使用这个简单的查询来检查新帖子:

    select topics.id, count(posts.id)
    from users
    inner join favorites on favorites.user_id = users.id
    inner join topics on topics.id = favorites.topic_id
    inner join posts on 
        posts.topic_id = topics.id and
        posts.id > last_post_id
    where users.id = $id
    group by topics.id
    

    这应该运行得相当顺利。

    您还必须在每次用户访问主题时更新 last_post_id,但这应该非常简单。

    【讨论】:

    • 您好,感谢您的回复。我使用了类似的查询,但我没有使用 group by。这对整体性能有何影响?你有什么想法吗?
    • 我很确定带有或不带有 groub by 的查询将同时运行。但是,如果您的索引设置正确,这应该非常快。
    【解决方案3】:

    如果你在巨大的 all_posts 表上有一个索引 (topic_id, post_id),那么执行此查询的成本应该不会太高:

    select topic_id, count(*)
    from all_posts a
    inner join user_favorites u on u.topic_id = a.topic_id
    where a.post_id > u.post_id and u.user_id = @user_id
    group by topic_id
    

    【讨论】:

      猜你喜欢
      • 2016-03-20
      • 2019-01-24
      • 2018-02-15
      • 2015-08-12
      • 2012-09-25
      • 2017-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多