如果您需要存储大量数据,那么您需要存储大量数据。如果你和大多数人一样,你可能不会在有钱解决问题之前就遇到这个问题。换句话说,您可能会假设您将拥有比您获得的更多的流量和数据,至少在短期内是这样。所以我怀疑这是一个问题,尽管这是一个好迹象,表明你现在而不是以后考虑它。
正如我在下面的评论中提到的,最简单的解决方案是为好友关系的每一方设置一个平局表(has_many :friends, through: :facebook_friend_relationships, class_name: 'FacebookFriend'
FacebookFriend 上的一个,根据下面提到的设计)。但是你的问题似乎是关于如何减少记录的数量,所以这就是答案的其余部分要解决的问题。
如果您必须存储在数据库中,并且您确定您肯定会让地球上的每个 FB 用户访问您的网站,因为它太棒了,但他们不会一次全部访问,那么如果您的存储空间有限,您可能还想使用 LRU 算法(删除最近最少使用的记录),也可能带有定时到期。您可以有一个 cron 作业,在数据库上执行查询,然后删除旧/未使用的记录来执行此操作。不会是完美的,但这将是一个简单的解决方案。
您还可以归档旧数据而不是将其丢弃。因此,经常使用的数据可能会保留在活动用户表中,然后您可能会将旧数据卸载到另一个表甚至另一个数据库(您可能会为此看到公寓和 second_base 宝石)。但是,一旦确定了规模,您可能会考虑一些与 ActiveRecord 模型/关联或模式设计关系不大的其他架构解决方案。尽管提前计划是值得的,但在您确定应用程序将获得足够多的用户来投入时间之前,我不会过度担心这一点。
即使 ActiveRecord 有一些缓存,您也可以在一开始就避免使用数据库并将朋友缓存在内存中以提高速度,尤其是在您还没有很多用户的情况下,您可能还没有。如果您认为由于大量用户而导致内存不足,LRU 在这里也可能是一个不错的选择,而且lru_redux看起来很有趣。同样,您可能希望缓存也过期并在缓存过期时重新获得朋友。即使只是将结果存储在用户会话中也可能就足够了,即在控制器操作方法中,只是 do @friends ||= Something.find_friends(fb_user_id)
,而后者是大多数人在开始时可能会做的第一次尝试。
如果您使用 ActiveRecord,请在控制器中的查询(或模型中的关联)中考虑使用include:
以避免 n+1 查询。这将加快速度。
对于架构设计,也许:
- 用户 - 包含电子邮件和身份验证信息的用户表。看看设计宝石。
- FacebookUser - 关于 Facebook 用户的信息。
- FacebookFriendRelationship - 具有(id 和)两列的关系模型,一列用于一个 FacebookUser id,另一列用于另一列。
通过将 authN 信息(用户)与 FB 数据(FacebookUser 和 FacebookFriendRelationship)分开,您可以更轻松地拥有其他社交媒体帐户等,每个帐户在其他表中都包含特定于这些帐户的信息。
如果目标是最小化关系表中的行,那么复杂性来自 FacebookUser 与朋友的关系。对于一半的行数,您将有一行用于 FacebookUser 的 id 可以在任一外键列中的关系。用户有朋友或者是朋友,所以你可以有两个has_many :through
FacebookFriend 上的关联,每个关联在 FacebookFriendRelationship 中使用不同的外键。或者您可以在没有模型的情况下执行 HABTM,并在每个关联中使用 foreign_key 和 association_foreign_key 选项。无论哪种方式,您都可以添加一个方法来将两个关联添加在一起(因为它们是数组)。相反,如果您不关心必须使用 ActiveRecord 以正常方式删除关联,则可以在单个 has_many 中使用自定义 SQL。但是,根据您的评论,我认为您希望避免这种复杂性,并且我同意您的观点,除非您确实必须限制关系行的数量。然而,吃掉数据的不是关系表的行数,而是你保存在 FacebookFriends 表中的所有用户信息。