介绍
这次又学习了数据库设计,所以总结一下内容。
我在 2021 年作为一名应届毕业生加入了一家网络开发公司,担任前端工程师,并将在 2022 年进入我的第二年。
在实践中Next.js x TypeScript我主要开发前端使用.
在最近的开发项目中导轨我是负责服务端开发的,接触过DB设计,但是没有系统的了解,所以苦苦挣扎。
虽然实现成功,但数据库设计改为“模糊的理解我系统地重新学习,这样我就不会以“.
为了学习数据库设计,我参考了以下书籍。
目标听众
- 想从基础开始学习数据库设计的人
- 有人在设计数据库
- 想要了解规范化的人
数据库和 DBMS
数据库是一个保持数据一致性和随时可用的系统。
还有一个数据库管理系统数据库管理系统(数据库管理系统)。
关系数据库 (RDB)
RDB是数据库中最流行的数据库。
RDB 以二维表的形式进行管理,可以直观地处理数据。
| 不同的d | 姓名 | 地址 |
|---|---|---|
| 1 | 山田 | 东京 |
| 2 | 铃木 | 大阪 |
| 3 | 长谷川 | 名古屋 |
关于系统开发
首先,我们将确认称为数据库设计的过程在整个系统开发中的位置。
系统开发流程
- 需求定义(确定系统将满足的功能和服务的需求)
- 设计(设计以满足定义的要求)
- 开发(根据设计文档实际开发)
- 测试(测试实现后是否真的实用)
- 维护和操作(操作开发的产品)
您可以逐步进行。
数据库设计包含在上面的步骤 2 中。
3 层架构
数据库设计中的一个重要概念图式我会解释一下
首先,模式是操作数据结构和数据库的规则和表达式的定义。数据库蓝图是。
架构也分为三个层次,一个三层架构架构。
三层架构是
- 外部架构
- 概念架构
- 内部架构
归类为
引用:https://itmanabi.com/db-schema/
外部模式
什么是外部架构从用户或应用程序端看到的定义数据库结构的模式。
我的意思是数据的视图、输出等,改变视图不会改变数据结构。
不同的d 姓名 年龄 地址 1 高桥 24 东京 2 中岛 18 千叶县 3 伊藤 39 埼玉 4 大桥 12 茨城县 5 中岛 25 千叶县 概念图式
概念架构是开发人员视角的数据库是。定义概念模式的设计逻辑设计也被称为
具体来说,它定义了数据元素和数据之间的关系。在数据库中创建表的蓝图。
内部模式
它定义了概念模式中定义的数据如何专门存储在 DBMS 中。硬件变化也在这里被吸收。
分为3层的原因
你们中的一些人可能想知道为什么首先有三层。
将其分为 3 层的原因是每个 schema 的更改不会影响其他两个。
如果每次发生规范更改时都会影响整个数据库,这将花费大量时间。
通过使用 3 层架构设计数据库,您可以在不更改视图或硬件的情况下维护和操作数据库。
逻辑设计和物理设计
逻辑设计步骤
逻辑设计是定义前面介绍的概念模式的设计。逻辑设计的一个特点是不受物理层(CPU、存储等)的约束。
在进行逻辑设计时,我们暂时搁置了物理层的限制。
基于这些前提,我们按照以下步骤进行逻辑设计。
- 提取实体
- 实体定义
- 标准化
- 创建 ER 图
实体提取
什么是实体实体代表
具体来说,EC 站点上的实体包括“商店”、“产品”、“客户”、“订单”和“付款”。
实体提取步骤是为实际开发的系统提取必要的实体。
实体定义
接下来,我们决定提取实体将保存什么样的数据。
实体拥有的数据属性(属性)。
在餐桌上柱子是属性。
store实体有属性
id,name,fee,所以列定义如下。[店铺]
不同的d 姓名 费用 1 优衣库 300 2 岛村 200 3 扎拉 500 产品实体有属性
id,name,price,所以定义列如下。【产品】
不同的d 姓名 价格 1 T恤 1000 2 瘦骨嶙峋的 200 3 教练夹克 500 客户实体有属性
id,name,address,email,所以定义列如下。【客户】
不同的d 姓名 地址 电子邮件 1 内藤 东京 naito@com 2 铃木 千叶 铃木@com 3 五十岚 埼玉 五十岚@com 至此,实体提取和实体定义已经完成。
正常化
然后正常化。规范化是一种使实体(表)更易于使用的设计。
规范化减少了数据冗余和不一致的机会。
我们将在后面的章节中更详细地讨论标准化。
创建 ER 图
ER图是表示实体之间关系的图。
逻辑设计总结
定义概念模式的逻辑设计将按照以下过程进行。
- 提取实体
- 实体定义
- 标准化
- 创建 ER 图
如果您将EC站点的逻辑设计步骤想象为示例图,它将如下所示。
物理设计步骤
接下来,我们将解释确定用于存储由逻辑设计确定的数据的物理区域的存储方法的物理设计。
- 表定义
- 索引定义
- 硬件选型
- 存储冗余
- 文件物理布局
表定义
表定义基于逻辑设计中定义的概念模式,并且桌子我们将其转换为单位
在此阶段创建的模型物理模型叫。
索引定义
您可以通过添加索引来提高性能,这是一个非功能部分。
通过引用索引,可以直接访问目标数据存储的位置,可以提高搜索速度。
硬件尺寸
选择系统数据的估计存储空间。
我们将根据容量和性能进行选择。
首先,数据库必须为了高一致性而牺牲性能,而一致性必须为了性能而牺牲。交易有关系
硬件大小调整需要以下输入信息。
- 系统使用的数据量
- 服务结束时的数据增长率
然而,在实践中,可能难以准确估计服务结束时的数据量。
假设数据量会增加,高扩展性配置。
冗余存储配置
存储的冗余配置意味着放置一个备用并配置多个存储,以便在存储由于故障而变得不可用的情况下快速恢复。
具体来说,RAID 用于使数据冗余。
关于 RAID 的详细说明这里省略,有兴趣的可以参考这里。
文件的物理排列
一旦确定了冗余配置,最后一步就是决定将数据库文件放置在哪个磁盘上。
存储在数据库中的文件可以分为以下五种类型。
- 数据文件:保存用户存储在数据库中的数据的文件
- 索引文件:存储在表上创建的索引
- 系统文件:管理用于内部 DBMS 管理的数据
- 临时文件:临时数据存储。使用 GROUP BY 等时对数据进行排序。
- 日志文件:用于表数据更改的临时存储文件
其中,开发商数据文件什么时候索引文件必须意识到。
备份设计
当数据由于故障等而丢失时,备份设计被设计为可以恢复。
备份主要分为三种类型:
- 完全备份
- 差异备份
- 增量备份
完全备份
顾名思义,此方法会备份备份位置上保存的所有数据。
虽然后卫非常简单,但他们也有自己的缺点。
- 备份时间长
- 硬件资源负载高
- 必须停止服务
差异备份
仅完整备份第一个数据,然后仅备份差异。
如果第三次后的第二天出现故障,数据丢失,可以用第一次和第三次的文件恢复。
增量备份
增量备份消除了差异备份的冗余。
增量备份是三种方法中数据量最少的一种,但也有恢复过程最复杂的缺点。
从上面可以看出,上面介绍的三种备份方式都有一个取舍的关系。
完全备份在要备份的数据量方面成本更高,但在发生故障时更容易恢复。另一方面,增量备份降低了要备份的数据量的成本,但使残疾儿童的恢复变得复杂。
我应该采用哪种备份
作为结论权衡各自的优缺点,根据系统的特点进行选择。.
一个要点
- 是否需要恢复?
- 可用于备份的时间
- 可用于恢复的时间
- 您需要保留多少代数据?
根据服务考虑这几点,选择合适的备份方式。
Tatsujin DB 列出了以下两种模式作为常用的方法。
- 完全备份 + 差异备份
- 完全备份 + 增量备份
至此,说明了逻辑设计和物理设计的一般流程。在下一章中,我们将详细解释逻辑设计中的规范化。
逻辑设计和规范化
表的组成部分
首先,表的结构在行中具有记录,在列中具有属性。
不同的d 姓名 年龄 1 高桥 24 2 铃木 21 3 伊藤 39 关于钥匙
数据库中有两个键:
- 主键
- 外键
主键称为主键每张桌子必须有一个始终可以通过指定主键来标识单行记录。
您可以看到 id 是上表中的主键。
不同的d 姓名 年龄 1 高桥 24 2 铃木 21 3 伊藤 39 作为主键之后的下一个最重要的键外键有。
外键是两个表之间的一组列。
例如,在下面的例子中,雇员表中的
department_id是一个外键。部门表
不同的d 部 1 销售量 2 人力资源 3 公共关系 员工表
不同的d 姓名 年龄 部门编号 1 高桥 20 1 2 铃木 24 3 3 伊藤 18 2 4 铃木 30 2 5 中岛 35 3 通过设置外键到员工表参照约束可以附上。
通过添加引用约束,您可以防止注册不存在的部门 ID。
关于约束
我刚刚介绍了参照约束引入了可以在除表之外的表上授予的约束
- NOT NULL 约束
- 唯一约束
- 检查约束
NOT NULL 约束
给出 NOT NULL 约束可防止在列中出现空白字段,如下所示。可以逐列指定 NOT NULL 约束。
NULL 在处理 SQL 时可能会很麻烦,因此最好在定义表时尽可能添加 NOT NULL 约束。
不同的d 姓名 年龄 1 高桥 24 2 21 3 伊藤 39 4 32 5 中岛 25 唯一约束
这是一个要求特定列具有唯一性的约束。
例如,用于防止会员注册网站上的电子邮件地址重复。
在以下情况下,id2 的铃木先生和 id4 的铃木先生的电子邮件地址重复。
不同的d 姓名 电子邮件 1 高桥 takashi@com 2 铃木 铃木@com 3 伊藤 itou@com 4 铃木 铃木@com 5 中岛 中岛 CHECK 约束
指定列的可能值范围的约束。
例如,如果您想设置 20 岁或以上的年龄限制,请使用此约束。
您可以阻止 20 岁以下的人输入数据,如下所示。
不同的d 姓名 年龄 1 高桥 24 2 中岛 18 3 伊藤 39 4 大桥 5 5 中岛 25 关于标准化
规范化被定义为一种数据格式,它消除了存储在数据库中的数据的冗余并保持一致性和效率。
规范化防止相同的信息存在于多个表中并导致浪费空间和更新处理。 (冗余)
一开始,从第一次归一化到第三次归一化理解就可以了。
第一次归一化
第一次归一化消除了一条记录中的多个值,如下图所示,使一个单元格只包含一个值。
在第一次标准化之前
姓名 年龄 部 高桥 20 销售量 铃木 24 人力资源
公共关系伊藤 18 发展
公共关系铃木 30 文职工作 中岛 35 销售量 第一次标准化后
姓名 年龄 部 高桥 20 销售量 铃木 24 人力资源 铃木 24 公共关系 伊藤 18 发展 伊藤 18 公共关系 铃木 30 文职工作 中岛 35 销售量 第二次归一化
做第二次归一化功能依赖什么时候部分功能依赖你必须理解这个词
函数依赖,顾名思义,和
Y=f(X)一样,如果确定了X,就确定了输出Y。换句话说,在餐桌上如果确定了 X 列的值,则也确定了 Y 列的值意思是
例如,在下表中,如果确定了员工 ID,则确定了员工姓名。
员工ID 员工姓名 部门 1 高桥 发展 2 铃木 销售量 3 铃木 人力资源 4 伊藤 公共关系 此时,员工ID和员工姓名之间存在函数依赖关系。
我们继续下表中的第二次归一化。
在第二次归一化之前
公司代码 公司名称 员工ID 员工姓名 年龄 部门代码 部门名称 C0001 A银行 000A 中岛 40 D01 发展 C0001 A银行 000B 铃木 32 D02 人力资源 C0001 A银行 000F 高桥 45 D03 销售量 C0002 B公司 000A 小泉 50 D03 销售量 C0002 B公司 009F 加藤 23 D01 发展 C0002 B公司 010A 增田 31 D04 一般事务 该表满足第一次归一化。
这个表的主键是{Company Code, Employee ID},如果你知道这两个键,你就可以识别出它的值。
(示例)如果公司代码是 C0001,员工 ID 是 000F,高桥先生,42岁,销售部我明白。
至于公司名称,即使不知道员工ID,只要知道公司代码,就可以识别。
这样,如果主键的某些列(本例为{company code,employee ID})有从属列,则此关系为部分功能依赖叫。
也就是说,如果你知道部分主键(本例中为{company code,employee ID}),就可以识别出公司名称
{会社コード}→{会社名},因此可以说他们有部分函数依赖关系了解。第二次规范化删除了表中的部分功能依赖,并创建了一个只有完整功能依赖的表。
第二次归一化后
[员工表]公司代码 员工ID 员工姓名 年龄 部门代码 部门名称 C0001 000A 中岛 40 D01 发展 C0001 000B 铃木 32 D02 人力资源 C0001 000F 高桥 45 D03 销售量 C0002 000A 小泉 50 D03 销售量 C0002 009F 加藤 23 D01 发展 C0002 010A 增田 31 D04 一般事务 [公司表]
公司代码 公司名称 C0001 A银行 C0002 B公司 第二次规范化允许员工表完全依赖于功能,如果主键 {company code, employee id} 已知,则可以确定该值。
此外,如果不进行第二次标准化,如下所示,可能会为相同的公司代码输入不同的公司名称,但可以通过执行第二次标准化来防止这种错误。
公司代码 公司名称 员工ID 员工姓名 年龄 部门代码 部门名称 C0001 A银行 000A 中岛 40 D01 发展 C0001 一个广告 000B 铃木 32 D02 人力资源 第三次归一化
第三次归一化传递函数依赖你需要知道这个词
传递函数依赖意味着在确定 A 时确定 B。当B确定时,C就确定了。因此,它具有传递关系,即当A确定时,C也确定。
让我们检查一下下表,该表已进行了第二次标准化。
[员工表]
公司代码 员工ID 员工姓名 年龄 部门代码 部门名称 C0001 000A 中岛 40 D01 发展 C0001 000B 铃木 32 D02 人力资源 C0001 000F 高桥 45 D03 销售量 C0002 000A 小泉 50 D03 销售量 C002 009F 加藤 23 D01 发展 C002 010A 增田 31 D04 一般事务 [公司表]
公司代码 公司名称 C0001 A银行 C0002 B公司 可以看到employee表有一个函数依赖
{部署コード}→{部署名}。此外,主键 {company code, employee ID} 具有函数依赖关系
{会社コード, 社員ID}→{部署コード}。从以上
您可以看到传递函数依赖
{会社コード, 社員ID} → {部署コード} → {部署名}成立。第三次归一化后
【部门表】
部门代码 部门名称 D01 发展 D02 人力资源 D03 销售量 D04 一般事务 [公司表]
公司代码 公司名称 C0001 A银行 C0002 B公司 [员工表]
公司代码 员工ID 员工姓名 年龄 部门代码 C0001 000A 中岛 40 D01 C0001 000B 铃木 32 D02 C0001 000F 高桥 45 D03 C0002 000A 小泉 50 D03 C002 009F 加藤 23 D01 C002 010A 增田 31 D04 这使我们能够完成第三次归一化。
ER图
随着表(实体)数量的增加,很难理解表之间的关系。
通过使用 ER 图,您可以表达表之间的关系并解决此问题。
关系数据库是1比1“”一对多“”多对多”基本上分解成
识别表关系
首先,让我们在 ER 图中表达之前创建的员工表、公司表和部门表之间的关系。
【部门表】
部门代码 部门名称 D01 发展 D02 人力资源 D03 销售量 D04 一般事务 [公司表]
公司代码 公司名称 C0001 A银行 C0002 B公司 C0003 建造 [员工表]
公司代码 员工ID 员工姓名 年龄 部门代码 C0001 000A 中岛 40 D01 C0001 000B 铃木 32 D02 C0001 000F 高桥 45 D03 C0002 000A 小泉 50 D03 C002 009F 加藤 23 D01 C002 010A 增田 31 D04 首先,员工表和公司表之间存在以下关系。
- 公司有多名员工(公司为主体)
- 员工属于一个公司(员工主体)
基于上述关系,公司及其员工一对多可以看出有关系
也在公司表中建造如果您查看员工表,您可以看到没有属于 的员工。
更严格的表达方式是一家公司有 0~n 名员工”。 (在后面的ER图中表示)
让我们看一下另一个部门表。
- 部门有多名员工(部门为主体)
- 员工属于一个部门(员工为主体)
基于以上关系,部门和员工一对多可以看出有关系
实际的 ER 图如下所示:
另外,当我写 ER 图时,我d 等艾欧我在用着
关于标准化的性能
规范化需要在 SQL 语句中加入(JOIN),增加了处理成本。因此,规范化具有减慢 SQL 的缺点。
规范化在提高数据完整性和降低搜索性能之间进行权衡。
冗余与性能权衡
- 非规范化提高了搜索性能,但降低了更新性能
- 实时减少数据
- 设计更改时多次回溯
逻辑设计中的反模式
最后,我将解释逻辑设计中不应该做的设计(反模式)。
数组类型
不要使用 1999 年 SQL 全球标准中包含的“数组类型”,保持第一次规范化。 (没有那么受欢迎就结束了)
通过使用数组类型,可以输入如下所示的多个数据,从而导致不一致。
员工ID 员工姓名 部门 001 铃木 发展
人力资源002 加藤 营销 003 矶野 公共关系 004 中岛 销售量
公共关系单一参考表
在第三次规范化创建的下表中,公司和部门的表结构相同,因此可以将两个表合二为一。
【部门表】
部门代码 部门名称 D01 发展 D02 人力资源 D03 销售量 D04 一般事务 [公司表]
公司代码 公司名称 C0001 A银行 C0002 B公司 C0003 建造 【单参考表(二合一)】
代码类型 代码值 代码内容 公司 C0001 A银行 公司 C0002 B公司 公司 C0003 建造 部 D01 发展 部 D02 人力资源 部 D03 销售量 部 D04 一般事务 单一参考表的优点
- 由于表数减少,ER图变得更简单
- 可以共享代码搜索SQL
单一参考表的缺点
- 所有列都必须声明为可变长度字符串
- 搜索性能因大量记录而下降
- ER 图更简洁但可读性较差
如上所述,最好不要创建将多个表合并为一个的单个引用表。
表划分
一个表中的记录数可能接近数百万。在这种情况下,有一种称为表划分的方法来减少表中的记录数。
[产品表]
产品编号 产品名称 价格 001 T恤 800 002 瘦骨嶙峋的 2000 003 夹克 5000 004 下 10000 将其水平划分。
[产品表001~002]
产品编号 产品名称 价格 001 T恤 800 002 瘦骨嶙峋的 2000 [产品表003~004]
产品编号 产品名称 价格 003 夹克 5000 004 下 10000 这次为了一个样本,介绍了一个将数据分成4个案例的例子,但实际上有数百万的数据。
水平分区减少了访问的数据量并可以提高性能。
另一方面,横向分割有以下缺点。
- 没有语义上的拆分原因(除非要求提高性能,否则无需实现)
- 可扩展性差
- 除了水平分割之外,还有其他方法可以解决性能问题
聚合
以下两种方法通常用作表分区的替代方法。
- 过滤列
- 汇总表
过滤列
在下面的员工表中,缩小到仅公司代码、员工 ID 和年龄列,并重新划分表。
[员工表]
公司代码 员工ID 员工姓名 年龄 部门代码 C0001 000A 中岛 40 D01 C0001 000B 铃木 32 D02 C0001 000F 高桥 45 D03 C0002 000A 小泉 50 D03 C002 009F 加藤 23 D01 C002 010A 增田 31 D04 【员工表(提取年龄)】
公司代码 员工ID 年龄 C0001 000A 40 C0001 000B 32 C0001 000F 45 C0002 000A 50 C002 009F 23 C002 010A 31 我创建了一个新的小表(数据集市),它从员工表中提取了年龄列。
在处理大量数据时,这有望提高性能。另一方面,需要定期与雇员表本身同步。
更新员工表的年龄时,还必须更新仅年龄数据集市。
虽然这可以提高性能,但它有以下缺点:
- 需要与原始表同步数据
- 更新处理会增加负载
- 与原始表格不一致的时间可能更长
汇总表
汇总表是保存由聚合函数聚合的记录的表。
聚合函数是可以应用于一个列组的函数,包括
SUM()、AVG()、MAX()、MIN()和COUNT()。例如,假设您创建一个新表来汇总每个公司员工的平均年龄。
[员工平均年龄]
公司代码 平均年龄 C0001 35 C0002 32 这个汇总表可以大大降低 I/O 成本。
另一方面,随着缩小范围,可能会出现数据同步问题。
在最后
怎么样。这一次,我解释了数据库设计。
我自己还在学习中,所以希望能在这次学习的基础上加深对数据库设计的理解。
我通常为前台写文章,所以如果您也能阅读它们,我会很高兴。
参考
本文是参考以下信息编写的。
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308622948.html