目前,存在一个主活动表,用于存储给定活动的呈现的HTML(Jim添加了一个朋友,George安装了一个应用程序等)。此主活动表保留源用户,html和时间戳。
然后,有一个单独的(‘join’)表,只需保留一个指针,该对象应该在其朋友Feed中看到此活动,并指向主活动表中对象的指针。
所以,如果我有100个朋友,我做3个活动,那么连接表将会增长到300个项目。
显然这张桌子会很快成长。它具有不错的属性,但是,提取活动以向用户显示单个(相对)廉价的查询。
另一个选择是保持主活动表,并通过以下方式进行查询:
select * from activity where source_user in (1,2,44,2423,... my friend list)
这样做的缺点是,您正在查询可能永远不会处于活动状态的用户,随着朋友列表的增长,此查询可能变得越来越慢。
我看到双方的利弊,但是我想知道一些SO的人是否可以帮助我衡量选项,并提出一种方式或其他方式。我也对其他解决方案开放,虽然我想保持简单,不能安装像CouchDB等。
非常感谢!
解决方法
>您可以创建多个活动表,并在从数据库中获取数据时执行UNION ALL。例如,滚动他们每月 – 活动_2010_02等。只要你的例子 – 200K用户x 100个朋友x 3个活动= 60万行。对于Postgresql来说,并不是性能方面的关注,但是您可能会考虑到纯粹为了方便起见,最终也是为了轻松的未来扩展。
>
This has the disadvantage that you’re querying for users who may never be active,and as your friend list grows,this query can get slower and slower.
您是否要显示整个活动Feed,回溯到时间的开始?你在原始问题中没有提供太多的细节,但是我会猜测你会显示最后10/20/100个按时间戳排序的项目。一些索引和LIMIT子句应该足以提供即时响应(因为我刚刚在大约2000万行的表上测试)。在繁忙的服务器上可能会更慢,但这应该是硬件和缓存解决方案,Postgres不会成为瓶颈。
即使您提供的活动馈送回到时间的黎明,分页输出! LIMIT子句将会保存在那里。如果基于LIMIT的基本查询是不够的,或者如果您的用户有一长串不再活跃的朋友,您可以考虑将查找限制为最后一天/每周/月,然后提供列表朋友ids:
select * from activity where ts <= 123456789 and source_user in (1,... my friend list)
如果您有几个月或几年的表格,搜索的朋友ID将只能在第一个WHERE子句选择的行中执行。
只要我选择你现在考虑的两个解决方案之一。我也会看看像:
>重新考虑你对桌子的非正规化。是否存储预生成的HTML输出真的最好的办法?通过查找表的活动而不是在运行中生成模板输出,你会更好地表现出来吗?预先生成的HTML一开始就可以看起来更好,但是考虑像磁盘存储,API,未来的布局更改和存储HTML这样的东西毕竟不会那么有吸引力。查找表可能包含您可能的活动 – 添加好友,更改状态等,活动日志将引用该朋友的身份,如果其他用户参与活动,则可以参考该朋友的身份。
>预先生成HTML,但不将其存储在数据库中。将磁盘上的内容保存为预生成的页面。然而,这不是一个银弹,而且在很大程度上取决于您的站点上的写入 – 读取的比例。即公共论坛上的一个典型的讨论话题可能有十几条消息,但可以查看数百次 – 这是缓存的好候选人。而如果您的应用程序更加适应立即状态更新,并且您必须重新生成HTML页面,并在每次视图之后再次将其保存在磁盘上,那么这种方法没有任何价值。
希望这可以帮助。