我正在使用LAMP构建一个feed(rss,twitter,其他服务等)聚合器。它与Google阅读器非常相似,因为人们可以根据需要添加任意数量的Feed,然后能够一次阅读其Feed,对其进行排序,查看单个Feed或一组Feed。
我之前已经建立了这种类型的服务,但对于一小群有限的人来说,整个群组可以访问所有聚合的Feed项目。所以,这很简单。
但是,这一次,我正在构建一个人们可以订阅的服务,因此我可能(理想情况下)有数千个用户和数十万个订阅源,反过来,还有数百万个订阅源。
我对数据库模式的方法(简化)是这样的:
users (id, name, ...)
feeds (id, name, url, ...)
feed_items (id, title, timestamp, feed_id, ... )
user_feeds (id, user_id, feed_id, ...)
但是,由于用户可以订阅100个Feed,我正在尝试计划最佳和最优化的方式来查询数据库以查找他们订阅的Feed(或子集)的feed_items。
答案 0 :(得分:2)
我认为你走在正确的轨道上。我之前(几次)已经完成了这个,重要的是弄清楚哪个表需要包含哪些信息。例如,在我的USERS表中,我保留了用户订阅列表(或OPML)的缓存副本。如果您要允许用户跟踪每篇文章的读/未读状态,您可能希望将这些元数据保存在单独的表中。相反,我发现您已经为用户< - > Feed关系设置了一个关系表。这允许您在FEED表中保留每个Feed的一个副本,但是查询复杂性(和性能)的权衡可能不值得。考虑一下您希望运行的查询。
例如,我的用户的主“主页”是一个“文件夹”列表(即Google阅读器标签),其中的Feed被隔离,每个文件夹都标有该文件夹中未读文章的数量(不包括重复的文章)。即使有良好的索引,这也是使用关系方法的查询(并且速度慢)。但是如果你对它进行非规范化(即,FEEDS表可能包含每个feed的多个副本,并且架构包含user_id(在我的例子中,文件夹名称)),表格更大,但该查询很容易且是即时的。
此外,在我的POSTS表(或FEED_ITEMS - 无论如何)中,我存放了原始文章说明/内容:在DESCRIPTION_ORIGINAL列中编码,然后在DESCRIPTION列中放入“干净”版本。干净的版本是HTML清理,删除广告,修复已知的编码问题等。
答案 1 :(得分:0)
缓存在这里非常有用 - 您可以在用户编辑其Feed时执行Feed查询并将结果存储在memcache中。
然后您可以执行WHERE (feed_items.feed_id IN ( ... ))
,但我建议您也缓存这些查询的结果。