关系型数据库中好友关系的设计

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
简介: 设计一群注册用户的好友关系,各自要能查询到自己的好友列表。最早想过用图数据库来进行好友关系存储,但身边没有成熟的案例,网上的资料也比较少。所以还是决定采用传统关系型数据库MySQL来进行设计。

  接到需求,设计一群注册用户的好友关系,各自要能查询到自己的好友列表。最早想过用图数据库来进行好友关系存储,但身边没有成熟的案例,网上的资料也比较少。所以还是决定采用传统关系型数据库MySQL来进行设计。

  好友关系,如果简单设计成一张表的话,随着注册用户的增多,好友关系势必会呈指数级增加,当系统中用户为10个人时,那么完全添加好友的话,关系数据(假设A和B是好友只有一条数据)则为(9+8+...+1)即55条;当系统中注册用户的数量增长到1000个人时,关系数据最大值为(999+998+...+1)即499500。所以如何设计系统,让用户快速查询到好友关系,是个难点。

  这里给出一种思路:根据注册用户的某一个字段(如用户ID),将它的所有好友关系集中存放到一张表中,而不同的用户,会根据这个ID的不同,将它们的好友关系分别散列在不同的数据表中。这样达到了将数据表数据分散,减轻单表压力的目的。但是,按照这个思路设计时,好友的关系必须是双向的,否则A和B的关系,到底是以A的ID进行散列还是B的ID进行散列呢?这样一来,好友的关系数增加了1倍,但是如果散列的足够均衡,这个结果也是可以接受的。市面上很多好友关系在进行设计时,也是采用双向的方式,即A加了B,B同意之后,即建立了双向好友关系,当A删除B的好友关系时,B查询自己的好友列表时,会发现A还在,只有B再删除A,双向的好友关系才会消除。

  接下来的工作是如何将这个散列方案实施下来。这里有两个问题,一个是在初期规划时,我们可能并不知道这个社交群体最终的规模,即无法在初期就创建固定数量的关系表,这个表一定是当容量达到一定规模时动态增长的;第二个是,在追求每张表的数据均衡时,我们还要考虑一种情况,即如果初期存入的一批用户被散列到某张表中(即该批用户指向的好友关系存在该表中),而恰好该批用户的好友关系增长速度远远超过其他批次的用户,造成该表数据急速增长的情况,该如何处理?在此背景下,我们来考虑这个被散列计算的字段该怎么设计。

  对于以上问题,一个简单的思路如下:假设现在有t_a,t_b,t_c,t_d四张表,都用于存放关系,在它们远没有达到存储规划上限时,我们可以就简单根据现有的各自表的容量,来决定注册用户该字段计算出来该指向哪张表。比如a,b,c现在容量都达到了1000条,而d表的容量才100条,那么在注册用户时,我们就将用户该字段设计成计算结果指向d表。我们还可以设计一个容量因子,在单表数量超过预设上限*该容量因子(如0.7)时,即停止将新用户的字段值设计成计算结果指向该表。另外,如果我们设定一个好友关系上限,如最多500个好友,那么预设的表数据上限除以这个数量限制可以得到这张表最多存放多少个不同的用户,这种做法可以保证这些关系表数量不会异常增长到超过我们预设的上限。

  但是,如果我们的系统允许用户无节制的增加好友,那么当用户量不断增长时,上述方案就无法在系统规模不断增长之后还能保证单表关系数量不会突破限制。此时,限制一个用户所有的好友关系在某个单表的方案已经不现实,但我们还是应该尽量这么做,对于单个用户在单表中设置一个关系数量上限,当他的好友关系超过这个数量时,把它存在另外一张表中。那么,如何知道这个用户是否图破了单表存储的设定上限,拥有多张表存储了好友关系,我们可以在注册用户的字段时加一个标记字段,那么查到该用户即可知道这个信息,对于已经突破了单表设定上限的,我们可以再加一张表-突破关系存放表,某用户突破一次,那么在该表中即存一条数据,其中一个字段的值与该用户原先的散列计算值匹配起来可以确定这次突破后存放的新表名称。这样既可快速定位到这些新表的名称,从而查询出所有的好友关系,另外,好友关系表中对单表单用户的好友关系数量做出了限制,所以当有N个表存放了该用户的数据时,那么好友的数量即,(N-1)*固定容量+第N张表的好友数量,所以统计好友总数也不复杂,只需要知道第N张表的数量即可推算出总数。

  暂时想到这么多,欢迎评论留言补充思路或者其它拓展点。

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
5月前
|
小程序 JavaScript 安全
【微信小程序-原生开发】转发给好友/群,分享到朋友圈(含单页模式访问云开发数据库的方法)
【微信小程序-原生开发】转发给好友/群,分享到朋友圈(含单页模式访问云开发数据库的方法)
214 0
|
SQL 缓存 NoSQL
社交系统中用户好友关系数据库设计
社交系统中用户好友关系数据库设计
1266 0
|
JSON JavaScript 小程序
小程序里显示附近的人,云开发数据库实现附近的人,按照位置远近排序,附近多少公里内的好友
小程序里显示附近的人,云开发数据库实现附近的人,按照位置远近排序,附近多少公里内的好友
187 0
|
存储 SQL 分布式计算
用户/帖子/好友/订单中心如何进行数据库水平切分
用户/帖子/好友/订单中心如何进行数据库水平切分
|
数据库
LeetCode(数据库)- 好友申请II:谁有最多的好友
LeetCode(数据库)- 好友申请II:谁有最多的好友
94 0
|
数据库
LeetCode(数据库)- 好友申请l:总体通过率
LeetCode(数据库)- 好友申请l:总体通过率
103 0
|
5天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
19 3
|
5天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
24 3
|
5天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE 'log_%';`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
29 2
|
18天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
130 15