关系数据库设计中,用中间表好还是直接设定主外键关联好?

简介: 有人会对数据库有这样的疑问:因为大多数的数据库教程上都是告诉你关系数据库如何去创建1:1、1:N和N:M的数据库关系,但我发现很多开源产品中,并没有直接使用关系数据库的关系查询、关系删除等功能,而是直接在代码中对多个表的查询结果进行组合。

有人会对数据库有这样的疑问:

因为大多数的数据库教程上都是告诉你关系数据库如何去创建1:1、1:N和N:M的数据库关系,但我发现很多开源产品中,并没有直接使用关系数据库的关系查询、关系删除等功能,而是直接在代码中对多个表的查询结果进行组合。

这两种方式的优缺点是什么呢?为什么很多项目都选择后者呢?在一个中型以上的项目实践中,我该选择哪种方式,或是两种方式结合使用?


我想:

1,数据表与数据表之间有关联(Relationship)是肯定的,但是不一定要用外键(Foreign Key),为什么?外键本质是一种约束(Constraint),该约束决定了你在增删改查的时候都会有额外开销。【实际上数据库在处理外键的时候估计也是创建一个中间表根据中间表来做关联操作,完成后再删除】

2,“对于 “N对N” 的关系,两个 Model 之间肯定是需要一张中间表的,比如 Student、Class 之间选课关系,是多对多的,肯定需要一张 Enroll 的表来维持,记录两个表的主键(Primary Key),但是不需要在数据库层加外键约束,只需要加两个索引,或作为联合主键。

3,至于查询,尽量不用 JOIN。但是问题是我确确实实是需要知道多个表的信息。
比如我要知道某门课(Class,已知 ID)的信息,同时还有选上该课(Enrolled)的学生信息(Student)。
使用 JOIN ?没问题,我相信你可以写出一个很长的 JOIN 语句。
但是,可能有的地方大概这样实现的(伪代码):

 
 
  1. getClassInfo(@class_id)
  2. { SELECT class_col1, class_col2 FROM class WHERE class.id = @class_id }
  3. getStudentInfo(@class_id)
  4. { SELECT student_col1, student_col2 FROM student WHERE student.id IN (SELECT enroll.student_id FROM enroll WHERE enroll.class_id = @class_id) }

两种方案各有优缺。
后者最大的一个优点是灵活,比如我们引入缓存(Caching)。
一般来说,一个学校 class 数量不多,并且经常被查询,系统可能会引入缓存层(如 memcached、redis)来存放 class 对象。
那么上面的 getClassInfo 其实会变为

   
 
  1. {
  2.   if(memcached.has(@class_id) != null)
  3.   {
  4.       return memcached.get(@class_id);
  5.   }
  6.  
  7.   //查询数据库(只有 class 表),和上面的 SQL 一样
  8.   memcached.set(@class_id, class_object);
  9.   return class_object;
  10. }

相关实践学习
体验RDS通用云盘核心能力
本次实验任务是创建一个云数据库RDS MySQL(通用云盘),并通过云服务器ECS对RDS MySQL实例进行压测,体验IO加速和IO突发带来的性能提升;并通过DMS执行DDL,将数据归档到OSS,再结合云盘缩容,体验数据归档带来的成本优势。
相关文章
|
5月前
3操作工作表
3操作工作表
|
存储 SQL Java
Mysql数据库表字段设计优化(状态列)
初始状态码(java int 32 long 64),int 可以表示31种(除去0000),long可以表示63种(除去0000),当然不可能将0000赋值给初始状态,一般来讲,选择int还是long是根据具体业务需求来决定的。
581 0
Mysql数据库表字段设计优化(状态列)
|
关系型数据库 MySQL 数据库
MySQL数据库(14):表关系
MySQL数据库(14):表关系
133 0
|
数据库 索引
存在逻辑删除的表字段上建立唯一索引的巧办法 (逻辑删除与唯一索引)
设计数据库唯一索引时,经常会碰到唯一删除的键值,导致很难处理,这里就简单介绍一种巧办法,帮你快速解决该问题
1982 0
存在逻辑删除的表字段上建立唯一索引的巧办法 (逻辑删除与唯一索引)
|
Web App开发 API 数据库
零代码实现一对一表关系和无限主子表级联保存
本文主要介绍一对一关系和无限主子表在crudapi系统中的应用。一对一关系是指关系数据库中两个表之间的一种关系。关系数据库中第一个表中的单个行只可以与第二个表中的一个行相关,且第二个表中的一个行也只可以与第一个表中的一个行相关。
307 0
零代码实现一对一表关系和无限主子表级联保存
|
Java 数据库
不设外键:用程序来实现表之间的关联
Association 相信有很多同学都有使用过Hibernate框架的开发经验,尽管现在开发人员对Hibernate的褒贬不一,我们暂且不谈这个话题。
1756 1
|
前端开发 JavaScript .NET
【自然框架】 之 主从表的添加、修改
摘要 1、 这里不是说如何做一个人员管理,这里要说的是自然框架如何处理主从表的添加、修改。人员管理只是一个例子。2、 人员管理的表的“结构”。3、 Tab标签页,通过js脚本+iframe实现的Tab效果。
1498 0
|
SQL 数据库 关系型数据库
EFCore中如何移除主外键关系
目录 EFCore中如何移除主外键关系 场景介绍 主外键关系的问题 解决思路 禁止级联关系的生成 MicroFX.EntityFrameworkCore.RemoveForeignKey扩展 EFCore中如何移除主外键关系 场景介绍 我用EFCore写了一个blog程序,我要通过写文章来分享自己的知识,我定义了一个Article用来存放文章信息,我还定义了一个Category用来存放文章的分类,Category与Article是一对的关系。
3721 0