数据库设计与实现

article/2025/10/13 15:33:27

一个良好的设计对于数据库系统至关重要,它可以减少数据冗余,确保数据的一致性和完整性,同时使得数据库易于维护和扩展。

实体关系图

实体关系图(Entity-Relationship Diagram,ERD)是一种用于数据库设计的结构图,它描述了数据库中的实体以及它们之间的关系。从结构上来说,数据库的ERD主要包括实体、属性以及关系三个部分。

实体

实体代表了一种对象或者概念。例如,员工、部门和职位都可以被称为实体。实体包含一个或多个属性,实体在数据库中对应的就是关系表。

属性

属性表示实体的某种特性,例如员工拥有姓名、性别、工资等属性。属性在数据库中对应的就是表中的字段,字段拥有一个指定的名称和数据类型。下图是一个包含各种属性的员工实体(employee)。

其中,员工编号(emp_id)属性可用于唯一标识每一位员工,被称为主键(Primary Key)。主键可以是单个字段,也可以由多个字段组成。

关系

关系用于表示两个实体之间的联系,三种常见的关系类型包括一对一、一对多以及多对多的关系。
例如,一夫一妻制是一种典型的一对一的关系。一个员工只能属于一个部门,一个部门可以拥有多个员工,因此部门和员工之间是一对多的关系。一个学生可以选修多门课程,一门课程可以被多个学生选修,因此学生和课程之间是多对多的关系。

规范化设计

规范化(Normalization)指的是用于数据库设计的一系列原理和技术,它可以减少表中数据的冗余,增加数据的完整性和一致性。我们通常在创建逻辑ERD或者物理ERD时引入规范化技术。

数据异常

假如我们不考虑规范化设计,将部门、员工以及职位等信息全部存储到一个表中,得到的表结构如下图所示。


所示表中的每一行数据对应一个员工的信息,包括员工所在的部门、姓名、性别、职位等。显然,这种设计存在以下问题:

数据冗余

同一个部门的信息存储多份,占用了更多的磁盘空间。由于数据冗余,有时候也可能导致在不同的表中存储了重复的数据或者字段。

插入异常

如果我们想要成立一个新的部门,由于还没有增加新的员工,因此无法录入这个部门的信息。


删除异常

如果我们删除了某个部门的所有员工,该部门的信息也将不复存在。

更新异常

如果我们想要修改部门信息,必须更新与该部门相关的多个记录,执行效率低下。如果不小心忽略了某些记录的话,将会导致数据不一致。

为了解决这些问题,数据库引入了规范化过程。规范化过程使用范式(Normal Form)进行定义和衡量,范式就是关系模型需要满足的一种规范要求或者标准级别。

关系模型的创始人Edgar Frank Codd博士最早提出了第一范式(1NF)、第二范式(2NF)以及第三范式(3NF)。随后人们又提出了更高级别的范式,包括BC范式(BCNF)、第四范式(4NF)以及第五范式(5NF)等。每个范式都基于前面的范式进行定义,例如若要实现第二范式,需要先满足第一范式的条件。

第一范式

第一范式要求关系模型满足以下条件:

  1. 表中的字段都是不可再分的原子属性。
  2. 表需要定义一个主键(Primary Key)。

简单来说,首先就是每个属性要有单独的字段。在上面的不规范设计中,员工的个人电话和工作电话存储在一个字段中,破坏了原子性。另外,我们还需要为表定义一个主键,用于唯一地识别每一行数据。假如每个部门中的员工姓名不会重复(实际上并非如此),我们可以使用部门名称加上员工姓名作为主键。


因此,我们将“电话”字段拆分成两个字段就可以满足第一范式,如下图所示。

第一范式要求表中的字段具有不可分割的原子性。不过我们知道,原子虽然是化学反应中不可再分的基本粒子,但其在物理状态下仍然可以被分割,它是由原子核和绕核运动的电子组成的。因此,我们同样需要了解数据库设计中的字段不可分割到底是针对什么而言的。

例如,“姓名”实际上也可以拆分成两个字段:“姓氏”和“名字”。我们要不要进行拆分取决于应用程序如何使用这些信息。一般我们可以将“姓名”作为一个字段存储,但是某些应用可能会对其进行拆分,比如申请信用卡时填写的表单。这样我们在给客户发送消息时,可以方便地称呼其为“尊敬的某先生/女士”。

另一个类似的情况是地址信息,比如“××省××市××区(县)××小区”。我们应该将其存储到一个字段中,还是拆分成多个字段呢?大部分情况下,应用程序可能需要统计不同地区的用户数据,将地址拆分成多个字段可以便于分析。

图中的表结构仍然存在数据冗余的问题(部门和职位信息),这可能导致插入异常、删除异常以及修改异常等问题,因此我们还需要对其进一步规范化。

第二范式

第二范式要求关系模型满足以下条件:

  1. 满足第一范式。
  2. 非主键字段必须完全依赖于主键,不能只依赖于主键的一部分。


“部门地址”取决于“部门名称”,也就是依赖于主键的一部分。这种依赖关系被称为部分函数依赖(Partial Functional Dependency)。此时,部门地址信息存在冗余,这可能会导致各种数据异常问题。另外,职位信息也存在相同的问题。

我们可以将部门和职位信息分别单独存储到一张部门表中,并且在它们和员工表之间维护一个一对多的外键关系,如下图所示。

我们将员工信息拆分成了3个表,并且为它们分别增加了一个编号字段。这是因为姓名、部门名称、职位名称等信息并不适合作为主键。例如,当我们使用部门名称作为主键时,如果需要修改某个部门的名称,员工表中就需要相应地修改多条记录。通常我们可以为每个表增加一个与业务无关的字段作为主键。

第三范式

第三范式要求关系模型满足以下条件:

  1. 满足第二范式。
  2. 属性不依赖于其他的非主属性。

如果主键决定了字段A,字段A又决定了字段B,这种依赖关系被称为传递函数依赖(Transitive Functional Dependency)。考虑到在同一个部门中可能存在多个姓名相同的员工这种情况,我们直接在员工表中增加一个编号字段作为主键也可以满足第二范式的要求,如下图所示。

 
主键“工号”决定了“部门名称”字段,“部门名称”决定了“部门地址”字段。因此,以上表结构虽然满足第二范式,但是存在传递函数依赖,可能会导致数据的冗余和不一致。

表结构中将员工表拆分成了多个表,避免了传递函数依赖问题,因此满足第三范式。

此时,我们再来回顾一下非规范化设计时的几个问题:

  1. 部门、员工以及职位信息分别存储一份,并且通过外键建立了它们之间的关系,因此不存在数据冗余的问题。
  2. 如果我们需要成立一个新的部门,可以直接录入部门信息。这样就解决了插入异常的问题。
  3. 删除某个部门的所有员工不会影响该部门的信息,不存在删除异常问题。
  4. 如果我们需要修改部门信息,直接更新部门表即可,不会导致数据不一致的问题。

对于大多数的交易型数据库系统而言,满足第三范式就已经足够了。我们在进行数据库设计时,只需将不同的实体或者实体的关系单独存储到一张表中即可满足第三范式。

主键与外键

规范化设计

在设计数据库的结构时,还有一个需要考虑的问题,那就是外键(Foreign Key)。外键是数据库用来实现参照完整性约束的,可以保证数据的完整性和一致性。同时,外键的级联操作可以方便数据的自动处理,减少程序出错的可能性。

例如,员工属于某个部门,我们可以在员工表的dept_id字段中创建一个引用部门表主键字段dept_id的外键约束。此时,我们必须先创建部门,然后才能为该部门创建员工,不会出现员工属于某个不存在的部门的情况,从而保证了数据的完整性。

同样,如果我们想要删除一个部门,必须确保该部门中不存在任何员工,或者同时删除该部门下的所有员工。利用数据库的外键级联删除或者级联更新功能,可以自动删除相关的员工,或者将相关员工的所属部门修改为其他部门。

不过,虽然外键可以实现参照完整性约束,但是也可能会导致性能问题。因为数据库为了维护外键需要牺牲一定的性能,这在大数据量高并发的情况下可能导致性能明显下降。

除以上方法外,另一种解决方法就是在应用层实现完整性检查,因为应用程序相对比较容易扩展。但是这种方案也可能引起一些问题。首先,应用程序中的实现更加复杂,无法百分之百地保证数据的完整性,尤其是在多个应用程序同时共享一个数据库时。另外,缺少外键会导致表之间的关系不明确,需要依赖相应的文档进行说明。

总之,我们在系统设计之初应该尽量利用外键实现数据的完整性约束。如果随着业务的增长而出现了数据库性能问题,可以考虑在应用程序中实现约束检查。

反规范化设计

简单来说,规范化就是将大表拆分成多个小表,并且通过外键建立它们之间的联系。规范化带来的一个结果就是连接查询。例如,为了查看员工所在的部门和职位,我们需要关联查询employee、department以及job表。

如果表中的数据量很大,多表连接可能会导致大量的磁盘I/O,从而降低数据库的性能。因此,有时候为了提高查询性能,可以降低规范化的级别,也就是反规范化(Denormalization)。

常用的反规范化技术包括增加冗余字段、增加计算列、将小表合成大表等。例如,我们需要连接查询department和employee,才能得到每个部门的员工数量。此时,我们可以在department表中增加一个存储员工数量的字段(emp_count),然后直接查询部门表就可以得到所需的信息。不过,我们每次增加或者删除员工时,需要同步更新部门表中的emp_count字段。

规范化增加了数据维护的开销和数据的冗余,可能会导致数据完整性和一致性的问题。因此,我们通常应该先进行规范化设计,再根据实际情况考虑是否需要反规范化。一般来说,数据仓库(Data Warehouse)和在线分析处理(OLAP)数据库会用到反规范化技术,因为它们以复杂查询和报表分析为主。


http://chatgpt.dhexx.cn/article/1vnkQthY.shtml

相关文章

数据库设计(二)——简单设计实例

Mysql设计步骤 一、设计一套系统数据库的步骤 1、实现什么样的功能(保证项目功能的完整性,列出所有模块)。 2、通过思维导图将每个功能模块串联起来(放射状,细节可以用文字描述)。 …

数据库设计的一般步骤

经过几天给韶关某个高校进行数据库设计的实训,对数据库设计的过程有了更加深刻的理解。 一、数据库设计的步骤 (1)了解功能需求 在设计数据库之前,设计人员必须要先了解系统的功能需求。这里可以通过阅读产品需求规格说明书&…

9.数据库设计

数据库设计 1、数据库设计概述 数据库设计。广义地讲,是数据库及其应用系统的设计,即设计整个数据库应用系统;狭义地讲,是设计数据库本身,即设计数据库的各级模式并建立数据库, 这是数据库应用系统设计的一…

数据库设计-概念结构设计

文章目录 数据库设计概念设计结构概念结构设计ER模型的基本元素实体/实体集属性区别实体和属性联系 二元联系的关系1:11:nm:n 一元联系1:11:nm:n 三元联系 采用ER模型的概念设计设计局部ER模型例题设计全局ER模型全局ER模型的优化 数据库设计 数据库设计:构造最优的…

数据库设计—图书管理数据库系统设计

如下代码供学习交流,获取完整代码,请关注公众号(coding加油站)获取 1、项目简介 图书馆数据库,该项目同时提供pythonweb可视化展示界面,也可提供相关报告数据,可以用来作为数据库系统设计的期…

数据库设计(一)——数据库设计

一、数据库设计简介 按照规范设计,将数据库的设计过程分为六个阶段: A、系统需求分析阶段 B、概念结构设计阶段 C、逻辑结构设计阶段 D、物理结构设计阶段 E、数据库实施阶段 F、数据库运行与维护阶段 需求分析和概念结构设计独立于任何数据库管理系统…

数据库设计的六个基本步骤

按照规范设计的方法,考虑数据库及其应用系统开发全过程,可将数据库设计分为以下6个阶段,分别为:1.需求分析,2.概念结构设计,3.逻辑结构设计,4.物理结构设计,5.数据库实施&#xff0c…

数据库设计(一)

目录 数据库设计的基本概念: 数据库设计包括以下几个部分: 需求设计: 1、数据: 2、处理: 概念结构设计: 实体: 例如: 联系类型: 1、一对一: 2、一对多&a…

数据库:数据库设计(需求,设计,运行,维护)

1,数据库设计概述 1.1,数据库设计的基本概念 数据库设计是指对于一个给定的应用环境,构造(设计)优化的数据库逻辑模式和物理结构,并据此建立数据库及其应用系统,使之能够有效地存储和管理数据&…

数据库系统-数据库设计

数据库系统-数据库设计 数据库设计概述及六步骤简介 数据库设计是指对于一个给定的应用环境,构造最优的数据库模式,建立数据库及其应用系统,使之能够有效地存储数据,满足各种用户的应用需求。 数据库设计的特点 数据库设计是一…

学生成绩管理系统数据库设计--MySQLSQL Server

MySQL 数据库设计-学生成绩管理系统 设计大纲友情链接 1、医疗信息管理系统数据库–MySQL2、邮件管理数据库设计–MySQL3、点餐系统数据库设计–SQL Server4、商品管理系统数据库设计–SQL Server5、SQL Server医疗信息管理系统数据库【英文版-源码】–(Medical Ma…

数据库设计-网上书店系统

一、需求分析 1.1 用户分析 网上书店系统的使用者主要有三种:普通用户、会员和管理员。 普通用户:浏览图书、查询图书、注册成为会员等; 会员:浏览图书、查询图书、加入购物车、修改购物车、订购图书、生成及查看订单、查看修改…

数据库设计

数据库设计 一.数据库设计概述1.数据库设计的特点2.数据库设计方法3.数据库设计的基本步骤4.数据库设计过程中的各级模式 二.需求分析1.需求分析的任务2.需求分析的方法3.数据字典 三.概念结构设计1.概念模型2.E-R模型3.概念结构设计 一.数据库设计概述 ①数据库设计是指对于一…

机器学习之PCA

一、PCA基本介绍 PCA(Principal Components Analysis)-主成分分析算法 用于数据降维、可视化、去噪非监督学习算法 二、PCA工作原理 目标:每次将空间中多维的样本点映射到一条直线上(要保证样本点之间的间距最大,用方差衡量,即保…

PCA9536——填坑

0. 问题 使用PCA9536输出模式控制4个小灯,开始时候按几次就不显示了,以为是接线不稳定原因。 后来一按开机电源就不显示了,以为是其他器件电源不稳定导致。 1. 问题1排除 接线问题,重新接线,重新做端子,…

sklearn PCA

sklearn.decomposition.PCA class sklearn.decomposition.PCA(n_componentsNone, *, copyTrue, whitenFalse, svd_solverauto, tol0.0, iterated_powerauto, random_stateNone)官方:link PCA是特征降维中一种 线性降维 的方法。 与特征选择不同(直接筛…

使用PCA对彩色图片降维

PCA对图片降维 1.原图片2.PCA降维思路3.代码4.k5效果图5.结论 1.原图片 2.PCA降维思路 1、小灰灰图片(407,367)2、求图片407行每行的均值mean,再将407行每行元素各自减去对应行的均值mean,即去中心化。得矩阵X&#xf…

使用PCA拟合平面

PCA原理&使用PCA拟合平面 背景三点确定一平面多点拟合平面基础数学知识PCA基本思想PCA拟合平面计算过程 PCA理解中心化协方差对角化 背景 本文参考以下两篇平面解析的论文。 《Fast Plane Extraction in Organized Point Clouds Using Agglomerative Hierarchical Cluster…

Dynamic inner PCA 和 Dynamic PCA

动态PCA方法的核心思想: 将数据X变成增广矩阵,即: l为潜在变量数,然后对X进行传统的PCA方法进行求解,即是动态PCA的结果。 动态内模PCA与之不同,上述动态PCA的一大缺陷是增加了数据的维度,而动…

python实现PCA

★ PCA个人理解: PCA降维是通过变换坐标系,来尽可能的减少信息损失。 ★ PCA思路: 我们的初始矩阵为X,它是mn维的矩阵,其中:m是该数据集有m条记录,n是每条记录中有n个特征,X的基本格…