以适度可扩展的方式提供活动源项

时间:2010-02-06 22:15:48

标签: database database-design social-networking

我正在处理的应用程序有一个活动源,每个用户都可以看到他们朋友的活动(很像Facebook)。我正在寻找一种适度可扩展的方式来动态显示给定用户的活动流。我说“适度”因为我只想用数据库(Postgresql)和可能 memcached来做这件事。例如,我希望这个解决方案可以扩展到200k用户,每个用户有100个朋友。

目前,有一个主活动表存储了给定活动的渲染html(Jim添加了一个朋友,George安装了一个应用程序等)。此主活动表保留源用户,html和时间戳。

然后,有一个单独的('join')表,它只是指向应该在朋友提要中看到此活动的人的指针,以及指向主活动表中对象的指针。

所以,如果我有100个朋友,并且我做3个活动,那么连接表将增加到300个项目。

显然,这张表会很快增长。但它具有不错的属性,即向用户显示的获取活动只需要一个(相对)便宜的查询。

另一种选择是保留主活动表并通过以下方式查询:

select * from activity where source_user in (1, 2, 44, 2423, ... my friend list)

这样做的缺点是您要查询可能永远不会处于活动状态的用户,并且随着您的朋友列表的增长,此查询会变得越来越慢。

我看到双方的优点和缺点,但我想知道是否有些SO人可以帮助我权衡选项并提出一种方式或其他方式。我也对其他解决方案持开放态度,但我想保持简单,不要像CouchDB那样安装等。

非常感谢!

1 个答案:

答案 0 :(得分:12)

我倾向于拥有主活动表。如果你这样做,我会考虑实施这个:

  1. 您可以在从数据库中提取数据时创建多个活动表并执行UNION ALL。例如,每月滚动它们 - activity_2010_02等。只是按照你的例子 - 200K用户x 100个朋友x 3个活动= 6000万行。对于PostgreSQL来说,性能并不是一个值得关注的问题,但是你现在可能认为这只是为了方便,最终是为了毫不费力的未来扩展。

  2.   

    这样做的缺点是您要查询可能永远不会处于活动状态的用户,并且随着您的朋友列表的增长,此查询会变得越来越慢。

  3. 您是否要显示整个活动Feed,这可以追溯到时代的开始?您没有在原始问题中提供太多详细信息,但我猜测您将显示按时间戳排序的最后10/20/100项目。一些索引和LIMIT子句应足以提供即时响应(因为我刚刚在一个大约有2000万行的表上进行了测试)。在繁忙的服务器上它可能会变慢,但这应该是硬件和缓存解决方案的解决方案,Postgres不会成为那里的瓶颈。

    即使您确实提供了回溯到时间的活动供稿, paginate 输出! LIMIT子句将为您节省开支。如果带有LIMIT的基本查询不够,或者如果您的用户有一长串不再活跃的朋友,您可以考虑将查找限制为最后一天/周/月首先然后提供朋友ID列表:

    select * from activity 
      where ts <= 123456789 
        and source_user in (1, 2, 44, 2423, ... my friend list)
    

    如果您有一个跨越数月或数年的表,则只会在第一个WHERE子句选择的行中搜索friends id。

    这就是我现在正在考虑的两种解决方案之间的选择。我还会看一下这样的事情:

    1. 重新考虑你的表的非规范化。存储预生成的HTML输出真的是最好的方法吗?通过查找活动查找表并动态生成模板化输出,您会在性能方面做得更好吗?预先生成的HTML在开始时看起来似乎更好,但考虑诸如磁盘存储,API,未来布局更改和存储HTML之类的东西可能并不那么吸引人。查找表可以包含您可能的活动 - 添加朋友,更改状态等,如果其他用户参与活动,活动日志将引用该信息以及朋友的ID。

    2. 执行预生成HTML,但不将其存储在数据库中。将内容保存在磁盘上作为预生成的页面。然而,这不是一个灵丹妙药,在很大程度上取决于您网站上的写入读取比率。即公共论坛上的典型讨论主题可能有十几条消息,但可以被观看数百次 - 一个很好的缓存候选者。然而,如果您的应用程序更多地针对即时状态更新而且您必须重新生成HTML页面并在每次观看后再次将其保存在磁盘上,那么这种方法几乎没有价值。

    3. 希望这有帮助。