追随者/追随者数据库结构

2022-08-30 18:41:17

我的网站有一个关注者/关注者系统(如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将是引用“用户”表中 Id 列的外键。


答案 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 表是聚集的,因此二级索引的行为与基于堆的表不同,如果您没有意识到这一点,则可能会产生意外的开销。让代理主键无缘无故地添加另一个索引1,并使 {user_id、follower_id} 和 {follower_id, user_id} 上的索引比它们需要的更胖(因为聚集表中的二级索引隐式包含 PK 的副本)。id

上表没有代理键,并且(假设InnoDB)由两个B树(一个用于主/聚类键,一个用于二级索引)物理表示,这与在两个方向上搜索一样有效2。如果你只需要一个方向,你可以放弃二级索引,只去一个B树。id

顺便说一句,你所做的违反了原子性原则,因此违反了1NF。


1 每增加一个索引都会占用空间,降低缓存效率并影响 INSERT/UPDATE/DELETE 性能。

2 从追随者到追随者,反之亦然。


推荐