关注关系产生的四种关系状态

  • 关注
  • 粉丝
  • 双向关注(互粉)
  • 无关系

用词follower表示粉丝 -- 追随者
用词following表示关注 -- 追随

设计的结构必须能满足以下功能:

  • 查询关注列表
  • 查询粉丝列表
  • 查询双向关注列表
  • 判断两个用户的关系
  • 查询带关系状态的任一列表

第一种方案

用一行纪录表示关注和粉丝,字段u2的值表示粉丝,u1表示被关注者。

Table: user(用户表)

Table: follower(u2表示粉丝, u1表示被关注的人)

查询用户id = 1的关注列表

SELECT * FROM follower WHERE u2 = 1

查询用户id = 1的粉丝列表

SELECT * FROM follower WHERE u1 = 1

查询用户id = 1的双向关注列表

 SELECT t1.* FROM (SELECT * FROM follower WHERE `u2` = 1) AS t1 INNER JOIN (SELECT * FROM follower WHERE `u1` = 1) AS t2 ON t1.u1 = t2.u2;

判断两个用户的关系(id = 1 --> id = 5)

SELECT * FROM follower WHERE (u2 = 1 or u1 = 1) AND (u2 = 5 or u1 = 5) LIMIT 3

id = 1的用户查询所有 id < 5的用户,并显示关系

如上图所示,要查询的用户的那个圈,被分成了四个部分(上面讲的四种状态):

  • 关注了我的用户
  • 和我互粉的用户
  • 我关注了的用户
  • 我未关注的用户

以上复杂的集合关系,通过单一SQL根本无法实现。

要查询的用户与粉丝集合的交集:

SELECT * FROM (SELECT * FROM user WHERE id < 5) AS t1
INNER JOIN(SELECT * FROM follower WHERE u1 = 1) AS t2ON t1.id = t2.u2

要查询的用户与关注集合的交集:

SELECT * FROM (SELECT * FROM user WHERE id < 5) AS t1
INNER JOIN(SELECT * FROM follower WHERE u2 = 1) AS t3ON t1.id = t3.u1

其他的部分可以通过以上两步查询出来的数据,在内存中作计算得出。

因为关注关系是互相的,用一行纪录即可表示。以上的设计其实是把关注和粉丝的概念用一行纪录表达。这样会引来一个缺点,当follower非常大的时候,对follower表进行分片,如果按u1或者u2分片,假设按u1分片,那么将导致关注列表,即下面的查询要做聚合。

SELECT * FROM follower WHERE u2 = 1

选择u1分片后,u2 = 1的数据行将会落到不同的分片上。

SELECT * FROM follower_0 WHERE u2 = 1
UNION
SELECT * FROM follower_1 WHERE u2 = 1

而粉丝列表的查询不会受影响,同一个用户的所有粉丝分在一个片上。

SELECT * FROM follower_1 WHERE u1 = 1

如果按u2分片,同样也会导致粉丝列表会落在不同的分片上。两个查询不可能同时满足分片。

如果分片是跨数据库或者是跨主机的方案,问题会变得更复杂。

针对方片的优化方案

可以用冗余数据的办法来解决数据分片带来的问题,即将关注和粉丝分2个表存放。 用follower表存放粉丝
用following表存放关注

当用户Ub关注Ua,分别往follower, following写入一行纪录。 (Ua -> Ub) 只是他们表示的含义不同。

follower表示Ua的粉丝是Ub
following表示Ub关注Ua

分片的时候,同时对follower和following进行分片。同时上面分析的所有查询方法也要相应改变,思路还是一样,只是单个表的自联接变成2个表的联接。

以上方案缺点就是数据量会增加一倍,进行关注或者取消关注的写操作会多一次,要同时维护2个表的数据。

以上优化虽然解决了一些问题,但同时也带来一些问题。可见关系型数据库在处理用户关系的时候,表现得很吃力。我们不得不承认,虽然叫“关系”型数据库却不太懂得处理集合关系。

另一种方案

还有一种方案,即用一行纪录表示出两个用户之间的所有关系,此方案能节省很大的数据空占用。

字段: u1, u2, type

type=1 表示u2关注u1
type=2 表示u1,u2互相关注
type=0 表示u1,u2无关系(默认)

保证插入数据时,u1是被关注者,u2是粉丝(当然你也可以换过来,只是逻辑会变了)

每次写入数据时要检查当前的状态:

如果u1(1) -> u2(2)纪录已经存在(u2已经关注u1),这个时候u1再关注u2,只需要将type字段的值变为type = 2。

如果u1(1) -> u2(2) type(2)时,即u1和u2互相关注,如果有一个人取消关注,问题会很复杂,最坏的情况要修改整行纪录,交换u1,u2这两个字段的值,再修改type=1。

同时上面的方案查询也会变化。例如要查询id = 1的粉丝列表:

SELECT * FROM table WHERE u1 = 1 OR (u2 = 1 AND type = 2)

例如要查询id = 1的关注列表:

SELECT * FROM table WHERE u2 = 1 OR (u1 = 1 AND type = 2)

上面的方案只强调关注关系,双向关系只是在单一关系上用字段区分,关注的先后关系很明显,事务性更强。

查询id = 1的双向关注

SELECT * FROM table WHERE type = 2 AND (u1 = 1 OR u2 = 1)

这个方案虽然节省数据空间,但是不容易理解,而且写入时每次要检查判断当前的关系,逻辑上过于复杂。而且数据量大后,由于查询WHERE条件同时有u1和u2,很难进行分片。

其他一些问题

  • ua与ub的共同关注列表
  • ua与ub的共同粉丝列表
  • ua的关注列表里谁关注了ub

以上的关系计算大家可能很容易理解,但要在MySQL里实现,是非常难的。

id = 3与id = 2的共同关注列表:

SELECT  u1, COUNT(id) AS num FROM follower WHERE u2 = 3 OR u2 = 2
GROUP BY u1 HAVING num > 1

id = 3与id = 1的共同粉丝列表:

SELECT  u2, COUNT(id) AS num FROM follower WHERE u1 = 3 OR u1 = 1
GROUP BY u2 HAVING num > 1

当然你可以用集合的方法查询:

SELECT t1.u2 FROM
(SELECT  u2 FROM follower WHERE u1 = 3) AS t1INNER JOIN
(SELECT  u2 FROM follower WHERE u1 = 1) AS t2ON t1.u2 = t2.u2

id = 1的关注列表里谁关注了id = 5

SELECT u2 FROM (SELECT u2 FROM follower WHERE u1 = 2) AS t1
INNER JOIN
(SELECT u1 FROM follower WHERE u2 = 1) AS t2
ON t2.u1 = t1.u2

微博相互关注互粉mysql表实现相关推荐

  1. 微博相互关注互粉mysql表实现_相互关注互粉mysql实现

    关注关系产生的四种关系状态 关注 粉丝 双向关注(互粉) 无关系 用词follower表示粉丝 -- 追随者 用词following表示关注 -- 追随 设计的结构必须能满足以下功能: 查询关注列表 ...

  2. 微博相互关注互粉mysql表实现_数据库设计实现用户关注、被关注、互粉

    关系型数据库虽然存储用户的关系很简单,但是要求出用户关注被关注和互粉这种这块特别的麻烦,特别是用户A的粉丝与用户B的粉丝之间的关系,或者用户A的关注者与用户A自己的粉丝直接的关系等. 下面是一个要求: ...

  3. 微博相互关注互粉mysql表实现_新浪微博的“关注功能”数据库是如何设计的

    展开全部 你好.方法有二个: 我觉得是这样设计的e69da5e887aa62616964757a686964616f31333335343362 一个字段记录他所关注的好友信息 应该是json的 然后 ...

  4. 我的新浪微博欢迎大家互粉

    http://www.sina.com.cn/fiona620206新浪的微博,有微博的大家互粉下哈!

  5. 提高我们微博互粉的效率,使用一键关注Chrome扩展程序

    2016-11-28日更新:解决部分页面无法自动关注的问题 2014-10-28日更新:修复由于微博版本更新造成的不能翻页的问题! 2013.6.28日更新:新浪更改了HTML,造成插件不能自动翻页! ...

  6. 节省微博互粉时间,使用全自动一键关注Chrome扩展程序

    此扩展程序是"提高我们微博互粉的效率,使用"一键关注"Chrome扩展程序"的升级版本,目前只支持新浪微博,其他微博请使用老版本! 详细使用帮助参见: 安装使用 ...

  7. php微博互粉网站源代码,PHP联合【新浪微博】实现第三方登陆

    获取 APP KEY和 APP SECRET 第一步:请求用户授权的token [appkey]&redirect_uri=[回调地址]&response_type=code 请求参数 ...

  8. 这才是真正意义上的微博互粉工具

    记得刚开始使用微博的时候,没有什么粉丝关注,哪怕写了非常有意思的微博,也没有人看, 逐渐的对微博失去了兴趣:后来发现不少朋友在四处寻求互粉,心里便萌生了要开发这个微博互粉的想法, 让大家更有动力去写微 ...

  9. 微博开放平台应用构想:互粉率应用

    微博开放平台应用构想:互粉率应用 目前的互粉查询,查的是,你所关注的人,有多少关注了你.这个意义不太大.对于想增加粉丝的人,他其实想查一下,哪个帐号,他关注了,对方有多大的可能性也关注他.可能性越高, ...

最新文章

  1. Navicat工具里的empty table和truncate table的区别
  2. 设计模式之_Strategy_02
  3. redis缓存数据表
  4. ElasticSearch通配符 * 查询(英文检索)
  5. Spring Boot通过@RequestParam接收前端表单传来的数据
  6. 用 Go 构建一个区块链 -- Part 1: 基本原型
  7. 使用priority_queue实现Dijkstra
  8. html向php传中文没有值,php - 为什么我的PHP / HTML表单没有向我发送数据 - SO中文参考 - www.soinside.com...
  9. GAN变种介绍 - DCGAN、InfoGAN、CycleGAN、WGAN、Self-Attention GAN、BigGAN
  10. 支付宝第三方登录接口 php,PHP调用支付宝支付接口操作步骤
  11. LCD点阵液晶多级菜单设计
  12. 【艺术字签名生成器】】试卷家长签字居然被嫌弃了|“我觉得我还能再抢救一下,你看行嘛?“
  13. 视频传输协议之MPEG-DASH
  14. 关于Ilegal assignment(Quart II)问题的解决
  15. MySQL 数据库之实现热备份
  16. #PCIE# 8b/10b 编码
  17. 前端浏览器窗口直接展示pdf文件
  18. 字符串是python中特有的数据类型_d1
  19. 数据预处理—-(数据探索、数据清理、数据集成、数据规约、数据变换)
  20. Oracle项目管理系统之费用与成本

热门文章

  1. Java 按顺序输入正方形的边长(a),长方形的长(l)和宽(d),以及圆的半径(r),计算并比较它们哪个图形面积更大,输出面积最大的图形
  2. 【Qt象棋游戏】07_人机博弈算法开端
  3. 全球及中国前置汽车中冷器行业需求趋势分析及发展规划研究报告2021-2027年版
  4. Oracle EBS 取消订单行时提示 Error:WSH_NO_DATA_FOUND
  5. tcping实用小工具
  6. 服务器如何ghost系统安装,如何在Ubuntu Server 14.04 LTS上安装Ghost
  7. ibm tivoli_IBM Tivoli Access Manager:WebSEAL Kerberos连接
  8. Mac-XQuartz-linux
  9. Python爬取电商平台充气娃娃用户评价,看看用户体验是什么样的!
  10. 雅思备考笔记—小作文篇(柱状图)