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

简介: 有人会对数据库有这样的疑问:因为大多数的数据库教程上都是告诉你关系数据库如何去创建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,再结合云盘缩容,体验数据归档带来的成本优势。
相关文章
|
7月前
|
存储 数据安全/隐私保护
8、软件配置管理过程——所有表集合
8、软件配置管理过程——所有表集合
99 0
|
5月前
|
存储 SQL 缓存
MySQL设计规约问题之为什么要将大字段、访问频率低的字段拆分到单独的表中存储
MySQL设计规约问题之为什么要将大字段、访问频率低的字段拆分到单独的表中存储
|
Web App开发 API 数据库
零代码实现一对一表关系和无限主子表级联保存
本文主要介绍一对一关系和无限主子表在crudapi系统中的应用。一对一关系是指关系数据库中两个表之间的一种关系。关系数据库中第一个表中的单个行只可以与第二个表中的一个行相关,且第二个表中的一个行也只可以与第一个表中的一个行相关。
313 0
零代码实现一对一表关系和无限主子表级联保存
|
API
订单和产品的多对多表关系在crudapi系统零代码实现
在上一篇序列号管理中,产品和销售订单都是孤立的单表,本文通过crudapi中表关系(relation)管理将多个表连接起来,形成一个整体。 表与表之间的关系(relation),分成三种。 一对一(one-to-one):一种对象与另一种对象是一一对应关系,比如一个学生只能在一个班级。 一对多(one-to-many):一种对象可以属于另一种对象的多个实例,比如一张唱片包含多首歌。 多对多(many-to-many):两种对象彼此都是"一对多"关系,比如一张唱片包含多首歌,同时一首歌可以属于多张唱片。
304 0
订单和产品的多对多表关系在crudapi系统零代码实现
|
Java 数据库
不设外键:用程序来实现表之间的关联
Association 相信有很多同学都有使用过Hibernate框架的开发经验,尽管现在开发人员对Hibernate的褒贬不一,我们暂且不谈这个话题。
1761 1
|
存储 监控 Oracle
Oracle数据库实例、用户、表、表空间之间关系
数据库:   Oracle数据库是数据的物理存储。这就包括(数据文件ORA或者DBF、控制文件、联机日志、参数文件)。   其实Oracle数据库的概念和其它数据库不一样,这里的数据库是一个操作系统只有一个库。可以看作是Oracle就只有一个大数据库。
2166 0
|
SQL 数据库 关系型数据库
EFCore中如何移除主外键关系
目录 EFCore中如何移除主外键关系 场景介绍 主外键关系的问题 解决思路 禁止级联关系的生成 MicroFX.EntityFrameworkCore.RemoveForeignKey扩展 EFCore中如何移除主外键关系 场景介绍 我用EFCore写了一个blog程序,我要通过写文章来分享自己的知识,我定义了一个Article用来存放文章信息,我还定义了一个Category用来存放文章的分类,Category与Article是一对的关系。
3734 0
|
存储 索引 数据安全/隐私保护