一文搞定关系数据库设计要领,值得收藏!(1)

关系表设计


从上面的E-R图,我们一眼就能看出他们之间的联系,那该如何设计关系模式呢?

我们要知道,关系数据库设计的目的是为了生成一组关系模式,使我们能够既不必存储不必要的冗余信息,又能方便地获取信息。为了是我们方便的达到这个目的,范式设计应运而生。

Boyce-Codd范式

我们所知道的令人满意的范式之一是Boyce-Codd范式(BCNF)。如果对F+中所有形如 α→β 的函数依赖,其中 α⊆R 且 β⊆R,下面的定义至少有一个成立:

  • α→β 是平凡函数依赖(即 β ⊂ α)。(一般来说,平凡函数依赖并没有讨论意义,讨论的都是非平凡函数依赖,即 β ∉⊂ α 的情况)

  • α 是模式R的超码。

考虑如下关系模式及其相应的函数依赖:

  • 学生 = (学号,姓名,年龄,性别)

学号 → 姓名 年龄 性别

  • 课程 = (课程号,课程名,学分)

课程号 → 课程名 学分

  • 选修 = (学号,课程号,成绩)

学号 课程号 → 成绩

以上模式均属于BCNF。就拿第一组关系模式来说,学生上仅有的非平凡函数依赖,箭头左侧是学号,学号是该模式的一个候选码(候选码属于超码的子集),没有破坏BCNF的定义。

其实并不是每个BCNF都能保持函数依赖的,例如:

Banker-schema = (branch-name,customer-name,banker-name)

它表示的是一个客户在某一分支机构有一个银行账户负责人。它要求满足的函数依赖集F为

  • banker-name → branch-name

  • branch-name customer-name → banker-name

显然,Banker-schema不属于BCNF,因为 banker-name 不是超码。

我们可以将它分解得到如下的BCNF:

Banker-branch-schema = (banker-name,branch-name)

Customer-banker-schema = (customer-name,banker-name)

分解后的模式只保持了banker-name → branch-name,而branch-name customer-name → banker-name的依赖没有保持。

第三范式

当我们不能同时满足以下三个设计目标:

  • BCNF。

  • 无损连接。

  • 保持函数依赖。

我们可以放弃BCNF而接受相对较弱的第三范式(3NF)。因为3NF总能找到无损连接并保持依赖的分解。

具有函数依赖即F的关系模式R属于3NF,只要F+中所有形如 α→β 的函数依赖,其中 α⊆R 且 β⊆R,下面的定义至少有一个成立:

  • α→β 是平凡函数依赖(即 β ⊂ α)。

  • α 是模式R的超码。

  • β - α 中的每个属性 A 都包含在R的候选码中。

回到Banker-schema的例子中,我们已经看到了没能将该关系模式转化成BCNF而又保持依赖和无损连接的分解,但改模式属于3NF。在Banker-schema中,候选码是{branch-name,customer-name},所以Banker-schema上不包含候选码的就只有banker-name。

而形如 α → banker-name 的非平凡函数依赖都是以{branch-name,customer-name}作为 α 的一部分。由于{branch-name,customer-name}是候选码,所以符合3NF的定义。

每个BCNF都属于3NF,因为BCNF的约束比3NF更严格。

存储引擎的选择


关系模式一但确定,基本的数据库表结构就确定了,接下来就是表结构的详细设计了,这里先从存储引擎开始,MySQL提供的各种存储引擎都是根据不同的用例设计的。

下表概述了MySQL提供的一些存储引擎。

最常用的两种存储引擎:MyISAM和InnoDB。

  • MyISAM:MySQL 5.5.5以前,MyISAM作为MySQL的默认存储引擎。

  • InnoDB:MySQL 5.5.5以后,InnoDB作为MySQL的默认存储引擎。

另外,关注公众号Java技术栈,在后台回复:面试,可以获取我整理的 MySQL 系列面试题和答案,非常齐全。

何如选择?

选择标准: 根据应用特点选择合适的存储引擎,对于复杂的应用系统可以根据实际情况选择多种存储引擎进行组合。但是要知道组合使用的缺点:

  • InnoDB和非InnoDB存储引擎的组合对比,仅使用InnoDB存储引擎可以简化备份和恢复操作。MySQL Enterprise Backup对使用InnoDB存储引擎的所有表进行热备份。对于使用MyISAM或其他非InnoDB存储引擎的表,它会执行“热”备份,数据库会继续运行,但这些表在备份时不能修改。

下面是常用存储引擎的适用环境:

  • InnoDB:事务型业务场景首选。

  • MyISAM:非事务型的大多数业务场景。

  • Memory:数据保存到内存中,能提供极速的访问速度。(个人觉得可以使用Redis等NoSQL数据库代替)

字符集选择


存储引擎之后就是确定字符集,字符集的选择十分重要,不管是MySQL还是Oracle,如果在数据库创建阶段没有正确选择字符集,那么在后期需要更换字符集的时候将要付出高昂的代价。

如何选择?

建议在能够完全满足应用当下和未来几年发展的前提下,尽量使用小的字符集。应为更小的字符集意味着能够节省空间、减少网络传输字节数,同时由于存储空间小间接的提升了系统的性能。

不同的数据库有不同的字符集应用级别,分别为服务器级别、库级别、表级别、字段级别,通常推荐使用库级别或者表级别。因为库级别或者表级别在保有灵活性的同时,兼顾数据间字符集的统一,这可以给开发省去很多处理字符集的麻烦。

数据类型的选择


选择原则

前提:使用合适的存储引擎。

选择原则:为了获得最佳的存储,您应该在所有情况下尝试使用最精确的类型。

固定长度和可变长度

char 与 varchar

下面这个例子说明二者的区别:

请注意上表中最后一行的值只适用不使用严格模式时;如果 MySQL 运行在严格模式,超过列 长度的值不保存,并且会出现错误。

从 CHAR(4)和 VARCHAR(4)列检索的值并不总是相同,因为检索时从 CHAR 列删除了尾部的空 格。通过下面的例子说明该差别:

mysql> CREATE TABLE vc (v VARCHAR(4), c CHAR(4));

Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO vc VALUES ('ab ', 'ab ');

Query OK, 1 row affected (0.00 sec)

mysql> SELECT CONCAT(‘(’, v, ‘)’), CONCAT(‘(’, c, ‘)’) FROM vc;

±--------------------±--------------------+

| CONCAT(‘(’, v, ‘)’) | CONCAT(‘(’, c, ‘)’) |

±--------------------±--------------------+

| (ab ) | (ab) |

±--------------------±--------------------+

1 row in set (0.06 sec)

对于InnoDB数据表,内部的行格式没有区分固定长度和可变长度列,所有数据化行都使用指向数据列值的头指针,因此在本质上,使用固定长度的CHAR列不一定比使用可变长度的VARCHAR列要好。

因为,主要的性能因数是数据行使用的存储总量。对于占用空间来说,CHAR总是大于等于VARCHAR,所以,使用VARCHAR来最小化行数据的存储总量,进而减少磁盘I/O频率。

text 和 blob

在使用text或者blob类型的字段是需要注意一下几点,以便获得更好的性能:

  • 执行大量的删除和更新操作后,会留下很”空洞“,需要定期optimize table进行碎片整理;

  • 避免查询大型的text和blob。查询大型的text和blob会使一页能装下的数据量减少,增加磁盘I/O压力。

  • 把text和blob分离到单独的表中。这会把原来表中的数据列转变为更短的固定长度的数据行格式,这个十分有用。

浮点数和定点数

在MySQL中float、double是浮点数,decimal是定点数。

浮点数优势:在长度一定的情况下,浮点数能表示更大的数据范围。

浮点数缺点:精度问题。

友情提醒:在有关金钱交易方面浮点数慎用!!!

整数

MySQL支持SQL标准整数类型INTEGER(或INT)和SMALLINT。作为标准的扩展,MySQL还支持整数类型TINYINT、MEDIUMINT和BIGINT。下表显示了每个整数类型所需的存储空间和范围。

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
[外链图片转存中…(img-pvh4xoWK-1715185446880)]

[外链图片转存中…(img-yRnM9arM-1715185446880)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 20
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值