关注者/关注者数据库结构
Posted
技术标签:
【中文标题】关注者/关注者数据库结构【英文标题】:Followers/following database structure 【发布时间】:2013-11-13 02:09:53 【问题描述】:我的网站有一个追随者/追随系统(如 Twitter)。我的困境是创建数据库结构来处理谁在关注谁。
我想出的是创建一个这样的表:
id | user_id | followers | following
1 | 20 | 23,58,84 | 11,156,27
2 | 21 | 72,35,14 | 6,98,44,12
... | ... | ... | ...
基本上,我认为每个用户都会有一行包含他们的关注者和他们关注的用户的列。关注者和他们关注的人的用户 ID 用逗号分隔。
这是一种有效的处理方式吗?如果没有,最好的选择是什么?
【问题讨论】:
【参考方案1】:这是最糟糕的做法。这是反对规范化的。有2张单独的桌子。用户和 User_Followers。用户将存储用户信息。 User_Followers 会是这样的:
id | user_id | follower_id
1 | 20 | 45
2 | 20 | 53
3 | 32 | 20
User_Id 和 Follower_Id 将是引用 Users 表中 Id 列的外键。
【讨论】:
是的,这是我想出的第二个结构,但我认为这样做并不传统。谢谢。 @Vad 我确实不适用于 Oracle :) 规范化是关系数据库系统和数据的概念,只要这些系统存在,它就不会成为过去 :) @regulus 你能解释一下为什么我们需要一个 id 列吗? @Nuwannnz 我们不需要 Id 列,只是一种习惯。用户和关注者 ID 的复合键完全可以作为主键。 @regulus 嗨。你能解释一下我们如何使用这种建模方法来计算 Instagram 的关注/关注/朋友等吗?【参考方案2】:目前有比其他答案提出的更好的物理结构:
CREATE TABLE follower (
user_id INT, -- References user.
follower_id INT, -- References user.
PRIMARY KEY (user_id, follower_id),
UNIQUE INDEX (follower_id, user_id)
);
InnoDB 表是clustered,因此二级索引的行为与基于堆的表不同,如果您没有意识到这一点,可能会产生意想不到的开销。拥有代理主键 id
只是无缘无故地添加另一个索引1 并使 user_id, follower_id 和 follower_id, user_id 上的索引比它们需要的更胖(因为二级索引在聚簇表隐含包含 PK 的副本)。
上表没有surrogate keyid
,并且(假设是 InnoDB)物理上由两棵 B-Tree 表示(一棵用于主/集群键,一个用于辅助索引),这与它的效率差不多获取双向搜索2。如果你只需要一个方向,你可以放弃二级索引,只需要一个B-Tree。
顺便说一句,你所做的违反了atomicity 的原则,因此也违反了 1NF。
1 而且每增加一个索引都会占用空间,降低缓存效率并影响 INSERT/UPDATE/DELETE 性能。
2 从关注者到关注者,反之亦然。
【讨论】:
跟随呢? @Justacoder 对不起,我不明白这个问题。 问题是关于追随者和追随者的。但看起来你的答案只针对followers
。所以我在问,Following
呢?
@Justacoder 您可以从此模型中查询“谁是给定人的关注者”和“给定人关注的人”。答案中提到的两个索引使两个方向都有效。
@BrankoDimitrijevic 第二个索引有什么意义; UNIQUE() 当你有 PRIMARY KEY 时?【参考方案3】:
不,你描述的方法有一些问题。
首先,将多个数据点存储为逗号分隔的字符串存在许多问题。加入起来很困难(虽然您可以使用 like
加入,但它会降低性能)并且搜索起来困难且缓慢,并且无法按照您想要的方式建立索引。
其次,如果你同时存储了一个关注者列表和一个关注者列表,你会有冗余数据(A关注B的事实会出现在两个地方),这既浪费空间,也造成数据不同步的可能性(如果数据库在 B 的关注者列表中显示 A,但在 A 的关注者列表中未显示 B,则数据不一致,很难从中恢复) .
改为使用连接表。这是一个单独的表,其中每一行都有一个用户 ID 和一个关注者 ID。这允许将事物存储在一个地方,允许索引和连接,还允许您向该行添加其他列,例如显示以下关系何时开始。
【讨论】:
【参考方案4】:这种表示的一个缺点是每个关系都被编码两次:一次在一行中用于关注者,一次在行中用于关注者,这使得维护数据完整性变得更加困难并且更新乏味。
我会为用户制作一张表,为关系制作一张表。关系表如下所示:
id | follower | following
1 | 23 | 20
2 | 58 | 20
3 | 84 | 20
4 | 20 | 11
...
这种方式添加新关系只是插入,删除关系是删除。汇总计数以确定给定用户有多少关注者也更容易。
【讨论】:
以上是关于关注者/关注者数据库结构的主要内容,如果未能解决你的问题,请参考以下文章