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

关注

粉丝

双向关注(互粉)

无关系

用词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 follower t2 ON t1.u1 = t2.u2 LIMIT 10

判断两个用户的关系(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 t2

ON t1.id = t2.u2

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

SELECT * FROM

(SELECT * FROM user WHERE id < 5) AS t1

INNER JOIN

(SELECT * FROM follower WHERE u2 = 1) AS t3

ON 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 t1

INNER JOIN

(SELECT u2 FROM follower WHERE u1 = 1) AS t2

ON 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表实现_用MySQL实现微博关注关系的方案分析相关推荐

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

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

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

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

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

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

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

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

  5. 用MySQL实现微博关注关系的方案分析

    由于产品需求的需要,我们做的产品里要实现类似微博里的关注关系.本文是以MySQL为基础,分析用MySQL如何实现微博的关注关系,对理解关注关系有一定的意义. 关注关系产生的四种关系状态 关注 粉丝 双 ...

  6. MySQL学习笔记_关于MySQL的字符类型VARCHAR长度知识总结

    MySQL学习笔记_关于MySQL的字符类型VARCHAR长度知识总结 一.VARCHAR存储和行长度限制 1.VARCHAR(N)中,N指的是字符的长度,VARCHAR类型最大支持65535,指的是 ...

  7. mysql双机互备linux成功的_配置MySQL双机热备 - Linux服务器MySQL双机热备份试验_数据库技术_Linux公社-Linux系统门户网站...

    二.配置MySQL双机热备 传统模式都是采用MySQL双机互备,至于双机热备我搜索了大量的精华帖子都没有发现安装配置文档.故我的一个想法产生了:当建立新的数据库时,默认会建立到/usr/local/m ...

  8. mysql多大_洞悉MySQL底层架构:游走在缓冲与磁盘之间

    提起MySQL,其实网上已经有一大把教程了,为什么我还要写这篇文章呢,大概是因为网上很多网站都是比较零散,而且描述不够直观,不能系统对MySQL相关知识有一个系统的学习,导致不能形成知识体系.为此我撰 ...

  9. mysql加上判断_在mysql中where加if判断

    在mysql中where中多重条件if判断,项目需求如下: 好友关系中本身具有A,B,C三种角色,好友动态分为1,2,3,4,5种类型.A是必须具有的角色,如果具有A角色可查好友动态类型1,3,4 的 ...

  10. mysql amp;amp;_浅析mysql交互式连接amp;非交互式连接

    交互式操作:通俗的说,就是你在你的本机上打开mysql的客户端,就是那个黑窗口,在黑窗口下进行各种sql操作,当然走的肯定是tcp协议. 非交互式操作:就是你在你的项目中进行程序调用.比如一边是tom ...

最新文章

  1. 常用的数据结构-队列
  2. 给AI一张高清照片,分分钟还你细节满满的3D人体模型,GitHub标星3.6k | 在线可玩...
  3. oracle之数据同步:Oracle Sql Loader使用说明(大批量快速插入数据库记录)
  4. Atitit java 二维码识别 图片识别
  5. nginx重定向到其他url方法_高级开发必须掌握Nginx之四,if、set、return
  6. Linux系统管理员修炼三层次
  7. 再谈 BigInteger - 使用快速傅里叶变换
  8. OpenCV图像腐蚀函数erode()的使用
  9. 大数据WEB阶段(十三)JSP(一)JSP基础、JSP指令详解、四大域九大隐式对象总结
  10. jax-rs jax-ws_什么是JAX-RS注释? (第3部分)
  11. 2016 博客导读总结 amp; 个人感悟
  12. 怎么提高自己的系统架构水平
  13. 问题 A: 深度学习
  14. 5开发 时间格式化_2020年,前端开发者必备的10个VS Code扩展插件
  15. java spi_Java SPI(服务提供商接口)和ServiceLoader
  16. 如何用5年时间从菜鸟成长为技术总监?
  17. vs中无法加入断点进行调试的解决方案
  18. tomcat编码配置gbk_Tomcat运行环境编码设置
  19. SSM毕设项目户籍管理系统jrg02(java+VUE+Mybatis+Maven+Mysql)
  20. ASCII码值是怎么计算的,怎么计算arccos的值

热门文章

  1. 英雄无敌3pc移植android版,今日手游:全盘移植《魔法门之英雄无敌3》
  2. TexturePacker 图片加密
  3. 免费开源PHP商城系统介绍
  4. 华为程序员频交 Linux 内核补丁遭质疑,管理员后续回应:承认贡献,但请不要琐碎提交
  5. 勒索病毒的种类和传播方式
  6. 项目Beta冲刺(2/7)(追光的人)(2019.5.24)
  7. java 克隆对象_Java中克隆(Clone)一个对象
  8. 有些事现在不做,一辈子都不会做了
  9. 自下而上和自上而下的注意力:不同的过程和重叠的神经系统 2014sci
  10. 华为服务器用户名密码忘记,电脑坏了,腾讯云华为云忘记宝塔面板登陆名和密码怎么办?...