数据库表设计2:用户关注粉丝

前言:在社交类系统中,用户与用户的好友关系的设计必不可少,那么如何设计好友的数据库至关重要,本篇文章带大家学习一下微博关注粉丝数据表相关的设计方案。

1、用户好友关系分类

第一步,有一张用户表,表内包含用户的基本信息,比如账号、姓名、性别等信息。这里用tb_user表示用户信息表。

ID用户名
1张三
2李四
3王五
4赵六

第二步,需要将用户与用户直接建立好友关系。这里有两种情况:单向好友关系、互为好友关系。
- 单向好友关系:就是张三在李四的好友列表中,但李四没有在张三的好友列表中;
- 互为好友关系:如果张三和李四为好友,则双方都在彼此的好友列表中;

好友关系设计

无论上面两种关系的哪一种,好友关系表都可以使用下面的设计,表tb_friend:

IDuser_idfriend_id
112
213

示例中,张三拥有李四和王五两个好友。

单向好友模式

如果是单向好友模式,那么两个人互为好友关系则插入的数据应该是这样:

IDuser_idfriend_id
112
221

也就是张三是李四的好友,李四也是张三的好友。此时使用sql语句查询时只用限定user_id作为条件即可查询出用户的好友列表:

select * from tb_friend where user_id = 1

互为好友关系

因为是互为好友关系,则只需要插入一条数据即可。对应的查询语句为:

select * from tb_friend where user_id = 1 or friend_id = 1

当然也可以使用UNION ALL来实现:

select friend_id as friends from tb_friend  where user_id = 1
UNION ALL --使用UNION ALL,因为不存在重复的
select user_id as friends from tb_friend where friend_id = 1

注意事项:
- user_id1–>friend_id2和user_id2–>friend_id1是相同的记录,不需要重复插入;
- 为了快速判断两个人是不是好友,可在程序层插入数据前添加一个限制user_id1 < user_id2;
- 可加入缓存层(Redis或Memcached)来提高性能;
- 可从数据库层限制(user_id,friend_id)不可重复;

加入分组

如果好友数量比较多,关系比较复杂,可引入好友分组,可进行如下改造:

IDuser_idfriend_iduser_groupfriend_group
112好友同学
213同学同学

在数据库中添加了user_group,当前user给friend设置的分组,friend_group是当前user的朋友对其设置的分组类别。

于是,查询好友列表的SQL如下:

select friend_id as friends ,user_group as my_group from tb_friends where user_id = 1

UNION ALL

select user_id as friends , friend_group as my_group from friend_id = 1

小结

至此社交系统中好友关系的设计及SQL语句使用基本完成。可根据具体的业务情况进行修改。在查询除好友的id列表之后就可以进行好友信息的查询。此处需要注意的是如果用in语句来查询会有不走索引、sql语句大小限制、性能等问题,可考虑使用左连接进行查询。


2、用户关注粉丝表设计方案

  •  follow(关注关系表)
字段名类型索引注解
idprimaryKey()                             
user_idinteger()->unsigned()->notNull()normal用户
followed_userinteger()->unsigned()->notNull()关注的人的id
statussmallInteger()->unsigned()->defaultValue(1)关注状态:是否取消关注等
created_atinteger()->unsigned()->notNull()normal
updated_atinteger()->unsigned()->notNull()normal

用户每关注一个人,都会在表中添加一条数据

优点

a.设计简单,方便查询

b.可以区分关注的每一个人进行特殊处理(例如,不同人的关注事件,是否互粉,特别关注等),方便扩展

c.好写代码。

缺点

当用户量大时表数据量会非常庞大,因此必需要采用水平分表的方式将用户分散到多个表

例如,有10万用户,ID为1~10000的用户放在表1(follow_1), ID为10001~20000的用户放在表2(follow_2), 以此类推。

然而分表后又会面临另一个问题,当被关注者依照多个表反查自己的粉丝时将会非常麻烦。因此需要再建一个粉丝表

  • fans(粉丝表)
字段名类型索引注解
idprimaryKey()
user_idinteger()->unsigned()->notNull()normal用户
followerinteger()->unsigned()->notNull()粉丝
statussmallInteger()->unsigned()->defaultValue(1)关注状态:是否取消关注等
created_atinteger()->unsigned()->notNull()normal
updated_atinteger()->unsigned()->notNull()normal

此数据表依然需要做水平分表处理。


3、用户关注关系表创建

CREATE TABLE `com_wechat_user_follow` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `uid` bigint(20) NOT NULL DEFAULT '0' COMMENT '用户ID',
  `fid` bigint(20) NOT NULL DEFAULT '0' COMMENT '关注用户ID',
  `createtime` int(10) DEFAULT '0' COMMENT '关注时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户关注表';
  • 查询关注了哪些用户
select `uid` from `com_wechat_user_follow` where `uid`='你的id'
  • 查询被哪些用户关注了
select `uid` from `com_wechat_user_follow` where `fid`='你的id'
  • 查询和某个用户共同的关注列表
select * from `com_wechat_user_follow` where `uid` in ('你的id', '某个用户id')
  • 查询是否互相关注
select * from `com_wechat_user_follow` where `uid`='你的id' and `fid`='某个用户id' 
and `uid` in (select `fid` from `com_wechat_user_follow` where `uid`='某个用户id')

用户逻辑关系梳理

在用户关注粉丝模型中,有两种常见场景:

①查看自己的粉丝或者关注列表:

这种情况下最多会出现三种关系:
其中1表示仅为本人所关注的人,2表示仅为本人的粉丝,3表示互粉

 ②查看别人的粉丝或者关注列表:

此时是以别人的粉丝或关注者与自己的关系进行判定:

其中find表示别人的粉丝或关注列表,在这里统称为other,1表示other是本人所关注的,2表示other与本人互粉,3表示other是本人的粉丝,4表示和本人没有任何关系

缺点:

1.当用户量大时表数据量会非常庞大,因此必需要采用水平分表的方式将用户分散到多个表。

2.每一次使用该表时都要将整条数据取出进行计算,对资源耗费太过严重。

3.数据库瓶颈,并发受限。

基于MySQL存在的缺点,使用Redis的Hash数据类型配合使用。


4、使用Redis的Hash数据类型配合使用

Redis hash是一个string类型的field和value的映射表。

Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。

每个用户分一张hash表,表名为用户id(可加前缀或后缀)

用户每关注一个人,便在hash表中添加一条数据

优点

1.查询处理速度快。

缺点

1.消耗服务器内存和CPU。最好使用一台单独的服务器来运行 Redis

2.数据查询,处理不如关系型数据库灵活。

3.开发步骤复杂,学习成本高。


参考链接:

MySQL关于用户关注粉丝表的设计方案

MySQL关于用户关注粉丝表设计方案的思考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java架构何哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值