最新要闻
- 世界观热点:6月20日 11:03分 迈普医学(301033)股价快速拉升
- 日系还香吗?新一代本田皓影混动/插混上市:19.99万起要打比亚迪_世界报资讯
- 16.5亿打造!《封神三部曲》第一部7月20上映:预告片发布
- 全脂/低脂可选:特仑苏纯牛奶2.7元/盒大促(商超6元)
- 世界快看点丨微软明确不会涉足VR:市场实在太小
- 红魔8S Pro首发高频版骁龙8 Gen2!170万跑分比骁龙8 Gen3还猛 焦点速讯
- 【全球新要闻】对在建工程“全面体检”
- 最资讯丨失乐园电影迅雷下载 失乐园电影未删减版迅雷下载
- 债市相对更强,股市估值处相对低位-焦点速递
- 墓地无人汽车探测到“鬼影”!真相到底是什么?
- 上海双层敞篷观光巴士将永久退役:已达13年强制报废标准 后继无车
- 首创双枪充电遥遥领先!比亚迪腾势N7首批量产车下线
- 高考过后 多所知名大学校长纷纷出镜招生|全球短讯
- 新买不到一个月特斯拉充电冒烟爆炸 女车主:很失望 产生心理阴影_天天动态
- 世界观点:菲律宾多方人士反对日本强推核污染水排海:不要污染我们的海洋
- “泰坦尼克”号残骸观光潜艇氧气仅剩96小时 美加部署飞机搜寻
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
全球即时看!数据库三大范式(考试必备)
一:什么是数据库范式
设计关系数据库时,要遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。所以要想设计一个结构合理的关系型数据库,必须满足一定的范式。其实范式的英文名称是Normal Form,简称NF。它是英国人E.F.Codd在上个世纪70年代提出关系数据库模型后总结出来的。范式是关系数据库理论的基础,也是我们在设计数据库结构过程中所要遵循的规则和指导方法。
1:范式的作用
使结构更合理和规范化,消除存储异常,使数据的冗余减少。便于插入、删除和更新。其实减少数据的冗余,就是尽量让每个数据只出现一次,要获取指定的字段数据时就通过JOIN的方式来拼接获取最终的数据。 所以范式的作用就是用来解决数据冗余和增删改的异常,要判断一个数据库设计的是否存在问题就从这两点判断。
(相关资料图)
2:范式都包括哪些
目前关系型数据库有六种常见范式,按照范式级别,从低到高分别是:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯科德范式(BCNF)、第四范式(4NF)、第五范式(5NF,又称完美范式);数据库的范式设计越高阶,冗余度就越低,同时高阶的范式一定符合低阶范式的要求,满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般来说,在关系型数据库设计中,最高也就遵循到BCNF,普遍还是3NF。但也不绝对,有时候为了提高某些查询性能,我们还需要破坏范式规则,也就是反规范化。
3:基础数据准备
-- 创建数据库和没有任何约束的表信息CREATE DATABASE IF NOT EXISTS demo_nf CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;USE demo_nf;CREATE TABLE IF NOT EXISTS student( sno INT COMMENT "学号", sname VARCHAR(10) COMMENT "姓名", sdept VARCHAR(10) COMMENT "专业", mname VARCHAR(5) COMMENT "系主任姓名", cno INT COMMENT "选课编号", grade DECIMAL(5,2) COMMENT "成绩") CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;-- 添加数据INSERT INTO demo_nf.student VALUES(1001,"王生安","信息与计算机科学","李主任",2206,76.5),(1001,"王生安","信息与计算机科学","李主任",2207,80.0),(1002,"钱勤堃","分子科学与工程","王主任",2335,60.0),(1003,"周卓浩","地球信息科学与技术","崔主任",3222,89.5),(1003,"周卓浩","地球信息科学与技术","崔主任",3223,56.5),(1003,"周卓浩","地球信息科学与技术","崔主任",3224,32.5),(1004,"张灶冲","数学与应用科学","鲍主任",4125,66.5),(1004,"张灶冲","数学与应用科学","鲍主任",4126,70.0),(1004,"张灶冲","数学与应用科学","鲍主任",4127,64);-- 课程编号对于的课程(这里我就没建立关联表了,后面用不上)2206 -> "计算机组成原理" ; 2207 -> "算法与数据结构"2335 -> "无机化学"3222 -> "构造地质学" ; 3223 -> "空间测地学" ; 3224 -> "地质学"4125 -> "高等代数" ; 4126 -> "概率统计" ; 4127 -> "数学分析"说明:从上面的关系可以看出 知道学号可以查询出当前学生的具体:姓名(sname)、专业(sdept)、系主任姓名(mname) 知道学号号选课编号可以查询当前学生的具体:成绩(grade)数据查询信息: SELECT * FROM demo_nf.student; +------+-----------+-----------------------------+-----------+------+-------+ | sno | sname | sdept | mname | cno | grade | +------+-----------+-----------------------------+-----------+------+-------+ | 1001 | 王生安 | 信息与计算机科学 | 李主任 | 2206 | 76.50 | | 1001 | 王生安 | 信息与计算机科学 | 李主任 | 2207 | 80.00 | | 1002 | 钱勤堃 | 分子科学与工程 | 王主任 | 2335 | 60.00 | | 1003 | 周卓浩 | 地球信息科学与技术 | 崔主任 | 3222 | 89.50 | | 1003 | 周卓浩 | 地球信息科学与技术 | 崔主任 | 3223 | 56.50 | | 1003 | 周卓浩 | 地球信息科学与技术 | 崔主任 | 3224 | 32.50 | | 1004 | 张灶冲 | 数学与应用科学 | 鲍主任 | 4125 | 66.50 | | 1004 | 张灶冲 | 数学与应用科学 | 鲍主任 | 4126 | 70.00 | | 1004 | 张灶冲 | 数学与应用科学 | 鲍主任 | 4127 | 64.00 | +------+-----------+-----------------------------+-----------+------+-------+注意:在实际开发中一定不要以这种方式创建数据库,这案例只是为了引出范式的概念和优化方式
二:关系数据理论
1:关系模式
其实一个关系模式由五部分组成,是一个五元组:R(U, D, DOM, F)(1) R: 关系名R是符号化的元组语义; (2) U: 一组属性(就是表的列); (3) D: 属性组U中属性所来自的域; (4) DOM: 属性到域的映射; (5) F: F就是属性组U上的一组数据依赖(就是表的列存在的依赖关系);由于 D、DOM 对模式设计关系不大,因此可以把关系模式看作是一个三元组:R,当且仅当U上的一个关系r满足F时,r称为关系模式R的一个关系。其实作为一张二维表,对它有一个最起码的要求:每一个分量必须是不可分的数据项(后面会说范式)。满足了这个条件的关系模式就属于第一范式(1NF)。
2:数据依赖
其实数据依赖一般存在两种,分别是函数依赖(Functional Dependency,FD)和多值依赖(Multivalued Dependency,MVD)。
什么是数据依赖呢?大概可以分为如下几点:①:它是一个关系内部属性与属性之间的一种约束关系;其实就是通过属性间值的相等与否体现出来的数据间相互联系 ②:是现实世界属性间相互联系的抽象 ③:是数据内在的性质 ④:是语义的体现从上面的介绍难免有点晦涩难懂,举个例子:比如描述一个学生的关系,可以有学号(sno)、姓名(sname)、系名(sdept)等几个属性。由于一个学号只对应一个学生,一个学生只在一个 系学习。因而当“学号”值确定之后,学生的姓名及所在系的值也就唯一地确定了。属性间的这种依赖关系类似于数学中的函数y=f(x),自变 量x确定之后,相应的函数值y也就唯一确定了。类似的有sname=f(sno),sdept=f(sno),即sno函数决定sname,sno函数决定sdept, 或者说sname和sdept函数依赖于sno,记作sno→sname, sno→sdept。 其实上面的例子就像我们平时写编程的函数或方法一样,定义一 个fun(type e)函数一样,我们传入e的值(如上面的x)可以获得指定的y。 例:针对上面的介绍建立一个描述学校教务的数据库,该数据库涉及的对象包括学生的学号(sno)、姓名(sname)、所在系(sdept)、系主任 姓名(mname)、课程号(cno)和成绩(grade)。假设用一个单一的关系模式student来表示,则该关系模式的属性集合为:: U = {sno, sname, sdept, mname, cno, grade}现实世界的已知事实告诉我们: (1) 一个系有若干学生,但一个学生有他对应的姓名,并且还只属于一个系 (2) 一个系只有一名(正职)负责人 (3) 一个学生可以选修多门课程,每门课程有若干学生选修 (4) 每个学生学习每一门课程有一个成绩 于是得到属性组U上的一组函数依赖F:F={sno→sdept, sno→sname, sno->mname, sdept→mname, (sno, cno)→grade}如下图所示:
如果只考虑函数依赖这一种数据依赖,我们就得到了一个描述学生的关系模式:student。 下表是某一时刻关系模式student的一个实例,即数据表(但是,这个关系模式存在问题):
以上关系模式存在的问题:就像我之前说的,判断一个表设计的好不好就从“数据冗余+增删改异常”来判断为什么设计的表不好 ①:数据冗余太大比如,每一个系的系主任姓名重复出现,重复次数与该系所有学生的所有课程成绩出现次数相同,这将浪费大量存储空间。 (合理的方式应该把"系主任姓名"抽离出去,数据的获取则通过表与表的JOIN方式获取)②:更新异常(Update Anomalies)由于数据冗余,当更新数据库中的数据时,系统要付出很大的代价来维护数据库的完整性,否则会面临数据不一致的危险。 比如,某系更换系主任后,必须修改与该系学生有关的每一个元组。 ③:插入异常(Insertion Anomalies)如果一个系刚成立,尚无学生,就无法把这个系及其系主任的信息存入数据库。 ④:删除异常(Deletion Anomalies)如果某个系的学生全部毕业了,在删除该系学生信息的同时,把这个系及其系主任的信息也丢掉了。鉴于存在以上种种问题,我们可以得出这样的结论(后面会详细说明怎么拆分):student关系模式不是一个好的模式。一个"好"模式应当不会发生插入、删除、更新异常,数据冗余应尽可能少。为什么会发生这些问题? 这是因为这个模式中的函数依赖存在某些不好的性质。假如把这个单一的模式改造一下,分成3个关系模式(即做成3张表): s(sno, sname, sdept, sno→sdept, sno->sname); sc(sno, cno, grade, (sno, cno)→grade); dept(sdept, mname, sdept→mname) 这三个模式都不会发生插入、删除异常的毛病,数据的冗余也得到了控制。
三:函数依赖
1:什么是函数依赖
定义:设R(U)是一个属性集U上的关系模式,X和Y是U的子集。若对于R(U)的任意一个可能的关系r,r中不可能存在两个元组在X上的属性值相等,而在Y上的属性值不等,则称“X函数确定Y"或“Y函数依赖于X”,记作X->Y。
简单说就是,在一个表里面,属性X(主属性)可以映射到属性Y(非主属性),也就是说知道了X就能确定Y,称X为决定因素。如一张表的属性信息:U = {sno, sname, ssex, sage, sdept, mname} 以数学中的函数y=f(x)来说,自变量x确定之后,相应的函数值y也就唯一确定了。 属性X包含:学号(sno) 属性Y包含:姓名(sname)、性别(ssex)、年龄(sage)、系名(sdept)、系主任姓名(mname) 通过函数依赖我们可以得知: sname=f(sno) 通过sno可以得出sname;可以记作 sno->sname 列出其它:sno->ssex、 sno->sage、 sno->sdept、 sno->mname 假设sname的姓名不可重复,被当作了属性X,则会再多出一些函数依赖关系: sname->ssex、 sname->sage、 sname->sdept、 sname->mname 若存在多个属性X则会发生互相依赖: sname <--> sno 那属性Y之间存在依赖关系吗? 其实Y(非主属性)也会存在依赖关系(如:函数传递依赖),但是设计一张好的表尽量不要存在依赖关系。 如上面的关系:ssex 无法确定 sage, sage 无法确定 ssex总结:若X->Y,并且Y->X,则记为X<-->Y。若Y不函数依赖于X,则记为 X无法确定Y。
2:平凡和非平凡函数依赖
平凡函数依赖:X可以决定Y,但Y属于X,则称X->Y是平凡函数依赖。 如一张表的属性信息:U = {sno, sname, ssex, sage} 可以得出 sno=f(sno) ,就是sno->sno 再如一张表的属性信息:U = {sno, sname, ssex, cno, grade} 可以得出 sno=f(sno,cno) ,就是(sno,con)->sno或(sno,con)->cno 所以对于任一关系模式,平凡函数依赖都是必然成立的,它不反映新的语义。若不特别声明,我们总是讨论非平凡函数依赖。非平凡函数依赖:X可以决定Y,但Y不属于X,则称X->Y是非平凡函数依赖。 如一张表的属性信息:U = {sno, sname, ssex, sage} 可以得出 sname=f(sno) ,就是sno->sname 再如一张表的属性信息:U = {sno, cno, grade} 可以得出 grade=f(sno,cno) ,就是(sno,con)->grade总结:若X->Y,则X称为这个函数依赖的决定因素(Determinant) 若X->Y,Y->X,则记作X<-->Y。(X和Y互相决定) 若Y不函数依赖于X,则记作X不决定Y。
3:完全和部分函数依赖
完全函数依赖:在R(U)中,如果X决定Y,并且X存在多个,那么在获取Y时必须依赖全部的X才可以确定Y,则称Y对X是完全函数依赖 如一张表的属性信息:U = {sno, sname, ssex, cno, grade} 若要得出具体的grade属性则必须的依赖关系是:(sno,cno)->grade 因为我想知道某位学生的某一门课的成绩grade,那我必须得同时知道他的学号sno和课程号cno。 但如果我只知道一部分信息,如sno或者cno是不行的,因为此时称y[grade]完全依赖于x[sno,cno]。部分函数依赖:在R(U)中,若X决定Y,并且X存在多个,那么获取Y时不必需要依赖全部的X才可以确定Y,则称Y对X是部分函数依赖 如一张表的属性信息:U = {sno, sname, ssex, cno, grade} 如果我想知道某位学生的姓名sname,那我知道他的学号sno就可以了。 也就是说y[sname]只函数依赖于x[sno,cno]中的子集x[sno],此时称y部分函数依赖于x。注:若一张表里面只有一个X,那么将不会构成部分函数依赖
4:传递函数依赖
传递函数依赖:在R(U)中,Z函数依赖于Y,且Y函数依赖于X,并且Y不函数依赖于X,X不函数依赖于Y,那么我们就称Z传递函数依赖于X如一张表的属性信息:U = {sno, sdept, mname} 如果我知道了一个学生的学号sno,那我就能知道他所在的系sdept。(因为理论上一个学生只属于一个系) 如果我知道了某一个系sdept,那么我就能知道这个系的系主任的姓名mname。(一个系只有一个正的系主任) 也就是说,我知道了一个学生的学号sno,其实我就知道了他所在系的系主任的姓名mname。但这个过程中, 它们是不存在直接函数依赖的,我需要通过系名称sdept作为一个桥梁去把二者联系起来的。 可以得出:sno->sdept->mnane但是需要注意的是:如一张表的属性信息:U = {sno, sname, sdept} 如果Y->X,即X<-->Y, 则Z直接依赖于X,而不是传递函数依赖; 虽然我可以sno->sname->sdept;但是sno->sdept也是可以确定的
四:数据库码的说明
码是数据库系统中的基本概念,所谓码就是能唯一标识实体的属性,比如学生表中的id就能够唯一标识出一条具体记录的属性字段,除了id字段,其实学号字段或身份证字段都能标识出唯一一条记录的都可以称作为码,但是如学生性别和地址字段就无法唯一标识出具体的一条实体记录,所以这种字段无法被称为码;其实码是整个实体集的性质,而不是单个实体的性质。它包括超码、候选码和主码等。(其实码就和我们日常说的键是一回事)
下面以这个几个表字段说明: U = {sno, scardid, sname, sage, sdept}超码:是一个或多个属性的集合,这些属性可以让我们在一个实体集中唯一地表示一个实体。如果K是一个超码,那么所有包含K的集合也是 超码。可以看出sno(学号),scardid(身份证号)可以唯一标识实体的属性字段,那么它就被称为码,其实也可以被称为超码还要知道多个属性字段里面包含一个超码,那么也会变为超码(可以理解超集,里面包含一个码的超集),如: (sno)、(scardid)、(sno, scardid)都是超码 (sno,sname,sage)是超码,因为它是一个包含sno超码的集合;但是这个不是码 (sno, scardid, sname, sage)是超码 (sname, sage)不是超码候选码:能够唯一标识一条记录的最小属性集。若关系中的一个属性或属性组的值能够唯一地标识一个元组(一条记录),且它的真子集不能 唯一的标识一个元组,则称这个属性或属性组做候选码。比如上面的sno(学号),scardid(身份证号)都可以被称为最小的候选码;但注意的是(sno, scardid)组合起来将不在是候选码, 而是一个由多个属性组成并包含一个码的超码; 假设通过(sname, sage, sdept)三个属性可以定位一条记录,且少一个属性都无法定位具体的一条记录,则这个也被称为最小 的候选码,因为真子集不能唯一的标识一个元组;主码:主码其实指的是主键。主关键字(PRIMARY KEY)是表中的一个或多个字段,它的值用于唯一地标识表中的某一条记录。在两个表的关 系中,主关键字用来在一个表中引用来自于另一个表中的特定记录。主关键字是一种唯一关键字,表定义的一部分。一个表的主键可以由 多个关键字共同组成,并且主关键字的列不能包含空值。主关键字是可选的,并且可在CREATE TABLE或ALTER TABLE语句中定义。说白了就是被数据库设计者选中的,用来在同一个实体集中区分不同实体的候选码。选择的是那些从不或极少变化的候选码作为主码, 从上面的三个候选码中sno(学号)、scardid(身份证号)、(sname, sage, sdept)组合候选码,最合适做主码的就是sno(学号)和 scardid(身份证号)了,因为这个属性字段极少被修改全码:关系模型中的所有属性组组成该关系模式的候选码,称为全码。即所有属性当作一个码。若关系中只有一个候选码,且这个候选码中包 含全部属性则该候选码为全码。说白了就是表里面的全部属性都是码,那么就被称为全码外码:可以被称为外键(FOREIGN KEY),比如数据表R1中的某属性集不是R1的主码,而是另一个数据表R2的主码,那么这个属性集就是数据 表R1的外码。主属性:包含在任一候选码中的属性称主属性。简单来说,主属性是候选码所有属性的并集非主属性:不包含在候选码中的属性被称为非主属性。非主属性是相对于主属性相反的属性来定义的。主码和候选码的区别:主码可以唯一标识,候选码是可以作为主码的码,主码一定是候选码的子集,但候选码不一定是主码。
五:第一范式(1st NF)
一个关系模式R里的所有属性都是不可分的基本数据项,就是说要确保数据表中每个字段的值必须具有原子性,每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。
示例1:假设一家公司要存储员工的姓名和联系方式。它就创建一个如下表: +-----+--------+----------+--------------+------------------------+ | uid | emp_id | emp_name | emp_address | emp_mobile | +-----+--------+----------+--------------+------------------------+ | 1 | 1001 | 张三 | 安徽六安 | 17681111145 | | 2 | 1002 | 李四 | 安徽合肥 | 15589874589,13658957488| | 3 | 1003 | 王五 | 安徽安庆 | 14687485987 | +-----+--------+----------+--------------+------------------------+ 其实这张表就不符合1NF,因为这张表不满足“同一列中不能有多个值”;其中emp_mobile字段的第二行发现李四存了两个手机号。 应该改为如下方式(把上面存在一列多个值的数据拆分为2行数据): +-----+--------+----------+--------------+-------------+ | uid | emp_id | emp_name | emp_address | emp_mobile | +-----+--------+----------+--------------+-------------+ | 1 | 1001 | 张三 | 安徽六安 | 17681111145 | | 2 | 1002 | 李四 | 安徽合肥 | 15589874589 | | 3 | 1002 | 李四 | 安徽合肥 | 13658957488 | | 4 | 1003 | 王五 | 安徽安庆 | 14687485987 | +-----+--------+----------+--------------+-------------+示例2:下面的student表就不符合第一范式: CREATE TABLE student ( id int(11) NOT NULL PRIMARY KEY COMMENT "主键ID", sno int(11) DEFAULT NULL COMMENT "学号", student_info varchar(255) DEFAULT NULL COMMENT "学生信息(包含姓名,性别,年龄)") student_info字段为学生信息,它还可以拆分成更小粒度的字段,不符合数据库设计对第一范式要求的“每个字段的值必须具有原子性”。 将student_info拆分后如下: CREATE TABLE student ( id int(11) NOT NULL PRIMARY KEY COMMENT "主键ID", sno int(11) DEFAULT NULL COMMENT "学号", sname varchar DEFAULT NULL COMMENT "姓名", ssex varchar DEFAULT NULL COMMENT "性别", sage int DEFAULT NULL COMMENT "年龄")举例3:属性的原则性是主观的,不是说字段必须要原则性例如有些人设计student表中的姓名字段都是有好几种方式: 使用1个字段的(fullname),使用2个字段的(firstname、lastname),使用3个字段的(firstname、middlename、lastname); 为什么会有这么多种方式的属性设计呢?其实都是取决于业务和应用程序,如果应用程序需要分别处理student表中的姓和名,经常对”姓“ 进行查询,那就则有必要把它们分开。否则,不需要。 比如有的表address字段存储的是这种格式:“xx省xx市xx区xx镇”;但是业务或者应用程序的需要,把省、市、区、镇这拆分为4个不同的 字段存储都是有可能的
六:第二范式(2st NF)
第二范式要求在满足第一范式的基础上,还要满足数据表里的每一条数据记录,都是可唯一标识的(就是要有主属性)。非主属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函依赖)。
如一张表U = {p1,p2,np1,np2} 其中主属性有(p1,p2)非主属性(np1,np2) 那么候选码和主码都为(p1,p2);这时需要满足第二范式则np1字段和np2字段必须完全依赖(p1,p2),缺一个码都不行示例1:如学生表 student = ( U={sno, cno, grade} ) 关系中;(sno, cno)为主码,并且这个主码可以决定grade(成绩)信息, 但是一个sno(学号)字段不能决定成绩,而且一个cno(课程号)也不能决定成绩,只有(sno, cno)两个字段一起才可以决定当前 表上面的grade(成绩)信息,这就是满足了第二范式函数的完全依赖关系,即非主属性必须完全依赖于候选码(主码是候选码的子集)示例2:如学生表 student = ( U={sno(学号), sname(姓名), sdept(专业), mname(系主任名称), cno(课程号), grade(成绩)} ) 这里的候选码和主码都为(sno(学号), cno(课程号));我们可以通过候选码(或主码)来决定如下的关系: (sno,cno) -> (sname, sdept, mname, grade) 但是上面的关系中,主属性和非主属性不满足第二范式,因为数据表中的主属性子集之间还存在着如下对应关系: (sno) -> (sname, sdept, mname),这种就违背了第二范式的“非主属性对主码的完全函依赖” 对于非主属性来说,并非完全依赖候选码。这样会产生“数据冗余+增删改异常”,这可以参考上面的2.2介绍的数据依赖问题。 为了避免上面的问题出现,我们就需要进行拆分表结构来满足第二范式,拆分方式如下: 成绩表 = (U={sno, cno, grade}) 学生表 = (U={sno, sname, sdept, mname}) 其实拆分有个速记规则:”谁跟你好,复制自己,把它带走““谁跟你好”:站在主属性的视角看,看看非主属性哪个和我构成完全函数依赖; “复制自己”:站在刚才的主属性视角,把自己属性复制一份出去构建一张表如t1表; “把它带走”:站在之的非主属性上,把那些和我构成完全函数依赖的非主属性带走放到我最新创建的t1表里; 如上面的sno主属性和非主属性字段构成了完全函数依赖,那就要复制sno字段,并且把和我构成完全函数依赖的非主属性带走构建新表总结:1NF告诉我们字段属性需要是原子性的,而2NF告诉我们一张表就是一个独立的对象,一张表只表达一个意思。所以第二范式(2NF)要 求实体的属性完全函数依赖于主码。如果存在不完全函数依赖,那么这个属性和主码的这一部分应该分离出来形成一个新的实体,新实 体与未分离的实体之间是一对多的关系。
七:第三范式(3st NF)
第三范式是在第二范式的基础上,确保数据表中的每一个非主属性字段都要和主码直接相关,也就是说,要求数据表中的所有非主属性字段不能依赖于其它非主属性字段(就是在2NF基础上消除传递依赖)。比如不能存在非主属性A依赖于非主属性B,非主属性B依赖于主属性(主码)C的情况,即存在“A->B->C”的决定关系;通俗地讲,该规则的意思是说所有非主属性之间不能有依赖关系,必须相互独立。这里的主属性可以拓展为候选码。
示例1:现在有2张表分别为: 部门信息表 = (U = { 部门编号, 部门名称, 部门简介 }) 员工信息表 = (U = { 员工编号, 姓名, 部门编号}) 其实上面的这2张表就符合第三范式,部门表的部门编号为主码,其它非主属性依赖于主码;员工表的员工编号为主码,其它的非主属性也是 依赖于员工编号的这个主码; 但是若要给员工信息表增加一个”部门名称“字段就会破坏第三范式规范,因为非主属性之间不能存在依赖关系 以员工信息表里来说:部门名称->部门编号->员工编号;这就会造成传递依赖示例2:如学生表 student = ( U={sno(学号), sname(姓名), sdept(专业), mname(系主任名称), cno(课程号), grade(成绩)} ) 我们拆分了满足范式二的要求如下: 成绩表 = (U={sno, cno, grade}) 学生表 = (U={sno, sname, sdept, mname}) 但是要满足第三范式则需要“非主属性字段不能依赖于其它非主属性字段”;可以看出学生表中的非主属性(sname, sdept, mname) 里面的(sdept, mname)构成了传递依赖,其中非主属性sdept(专业)依赖于sno(学号), 而非主属性mname(系主任名称)则可以依赖于 非主属性sdept(专业),因为通过专业可以找到具体的专业里的系主任,所以需要如下修改,拆分学生表达到第三范式: 成绩表 = (U={sno, cno, grade}) 学生表 = (U={sno, sname, sdept}) 专业表 = (U={sdept, mname}) 其实拆分有个速记规则:”谁跟你好,复制自己,把它带走“;因为mname依赖sdept,所以以sdept为主码创建一张表,把依赖自己的复制 到新的表,然后剔除学生表的mname字段
八:范式1~3总结
关于数据表的设计,有三个范式需要遵循: 第一范式:数据库的每一列都是不可分割的原子数据项,不可再分的最小数据单元,而不能是集合、数组、多条记录等非原子数据项。 第二范式:确保每列属性都和主键完全依赖,尤其在复合主键的情况下,非主键部分不应该依赖于部分主键。 第三范式:确保每列都和主键列直接相关,而不是间接相关(传递依赖)范式的优点:数据的标准化有助于消除数据库中的数据冗余,第三范式(3NF) 通常被认为在性能、扩展性和数据完整性方面达到了最好的平衡。范式的缺点:范式的使用,可能降低查询的效率。因为范式等级越高,设计出来的数据表就越多、越精细,数据的冗余度就越低,进行数据查询 的时候就可能需要关联多张表,这不但代价昂贵,也可能使一些索引策略无效。范式只是提出了设计的标准,实际上设计数据表时,未必一定要符合这些标准。开发中,我们会出现为了性能和读取效率违反范式化的原则,通过增加少量的冗余或重复的数据来提高数据库的读性能,减少关联查询,JOIN表的次数,实现空间换取时间的目的。因此在实际的设计过程中要理论结合实际,灵活运用。总结:范式本身没有优劣之分,只有适用场景不同。没有完美的设计,只有合适的设计,我们在数据表的设计中,还需要根据需求将范式和反 范式混合使用。
九:反范式化
1:概述
有的时候不能一味的按照规范要求设计数据表,因为有的数据看似冗余,其实对业务来说十分重要。这个时候我们就要遵循业务优先的原则,首先满足业务需求,再尽量减少冗余。如果数据库中的数据量比较大,系统的UV(独立访客)和PV(网站浏览量)访问频次比较高,则完全按照MySQL的三大范式设计数据表,读数据时会产生大量的关联查询,在一定程度上会影响数据库的读性能。如果我们想对查询效率进行优化,反范式优化也是一种优化思路。此时,可以通过在数据表中增加冗余字段来提高数据库的读性能。
规范化 VS 性能:①:为满足某种商业目标,数据库性能比规范化数据库更重要 ②:在数据规范化的同时,要综合考虑数据库的性能I ③:通过在给定的表中添加额外的字段,以大量减少需要从关联查询得到的信息所需的时间 ④:通过在给定的表中插入计算列,以方便查询示例:employees = ( U={employee_id(编号), ename(姓名), essex(性别), department_id(部门id,其实也是外键)} ) departments = ( U={department_id(编号), department_name(部门名称), dmsg(部门信息)} ) 比如现在有两张表,员工的信息存储在employees表中,部门信息存储在departments表中。通过employees表中的department_id字段 与departments表建立关联关系。如果要查询一个员工所在部门的名称: SELECT e.employee_id, d.department_name FROM employees e JOIN debartments d USING(department_id); 假设数据量都已经达到50多万以上,而且还要经常需要进行这种的SQL查询操作,其中连接查询就会浪费很多时间;那么为什么不考虑在 employees表中添加一个冗余字段“department_name”呢,这样每次查询就不需要进行连接操作了(这种就是典型的反范式化); 改造的表(添加一个冗余字段): employees = ( U={employee_id(编号), ename(姓名), essex(性别), department_name(部门名称), department_id(部门id,其实也是外键)} ) departments = ( U={department_id(编号), department_name(部门名称), dmsg(部门信息)} )
2:反范式化的问题及适用场景
反范式可以通过空间换时间,提升查询的效率,但是反范式也会带来一些新问题:①:存储空间变大了 ②:一个表中字段做了修改,另一个表中冗余的字段也需要做同步修改,否则数据不一致 ③:若采用存储过程来支持数据的更新、删除等额外操作,如果更新频繁,会非常消耗系统资源 ④:在数据量小的情况下,反范式不能体现性能的优势,可能还会让数据库的设计更加复杂反范式的适用场景:当冗余信息有价值或者能大幅度提高查询效率的时候,我们才会采取反范式的优化。 Ⅰ:增加冗余字段的建议增加冗余字段一定要符合如下两个条件。只有满足这两个条件,才可以考虑增加冗余字段。 这个冗余字段不需要经常进行修改; 这个冗余字段查询的时候不可或缺。Ⅱ:历史快照、历史数据的需要在现实生活中,我们经常需要一些冗余信息,比如订单中的收货人信息,包括姓名、电话和地址等。每次发生的订单收货信息都 属于历史快照,需要进行保存,但用户可以随时修改自己的信息,这时保存这些冗余信息是非常有必要的。 反范式优化也常用在数据仓库的设计中,因为数据仓库通常存储历史数据,对增删改的实时性要求不强,对历史数据的分析需求强。 这时适当允许数据的冗余度,更方便进行数据分析。 简单总结数据仓库和数据库在使用上的区别: 1.数据库设计的目的在于捕获数据,而数据仓库设计的目的在于分析数据; 2.数据库对数据的增删改实时性要求强,需要存储在线的用户数据,而数据仓库存储的一般是历史数据; 3.数据库设计需要尽量避免冗余,但为了提高查询效率也允许一定的冗余度,而数据仓库在设计上更偏向采用反范式设计。
十:巴斯-科德范式(BCNF)
在第1~3范式的基础上进行了改进,提出了巴斯范式(BCNF),也叫巴斯-科德范式(Boyce-Codd Normal Form);BCNF其实并没有新的设计规范加入,只是对第三范式中设计规范要求更强,使得数据库冗余度更小。所以,称为是修正的第三范式,或扩充的第三范式,BCNF不被称为第四范式。 BCNF主要就是消除主属性对码(单码或复合码)的部分函数依赖和传递函数依赖;其实我们可以看出,第一范式解决了属性的原子性问题,第二范式解决了非主属性对码的部分函数依赖,第三范式解决了非主属性对码的传递依赖问题;那么有没有想过这样问题,假如当前有个表里面有特别多的主属性,其中主属性里面存在着主属性对主属性有着部分函数依赖和传递函数依赖,这样就会造成表的数据冗余和增删改的异常,其实这种主属性对主属性的函数依赖还是少见的,但是真的遇到了可以使用BCNF进行个表拆分。
如一张表U = {p1,p2,np1,np2} 其中主属性有(p1,p2)非主属性(np1,np2); 这时需要满足第二范式则np1字段和np2字段必须完全依赖(p1,p2),缺一个码都不行BCNF关系模式的性质: ①:所有非主属性都完全函数依赖于每个候选码如一张表U={p1,p2,np1,np2};其中主属性有(p1,p2)非主属性(np1,np2) 那么候选码和主码都为(p1,p2),下面就可以进行推断: 通过(p1,p2)-> np1 ,通过(p1,p2)-> np2 都是符合上面的定义 但是(p1)-> np1 这就不符合上面定义的非主属性都完全函数依赖于每个候选码,因为np1只部分函数依赖于p1 ②:所有主属性都完全函数依赖于每个不包含它的候选码比如现在有个表U={p1, p2, p3, np1, np2};其中主属性有(p1,p2,p3)非主属性(np1,np2) 现在(p1,p2)和(p2,p3)都是候选码,其中选择(p1,p2)为主码 那么现在(p1,p2)-> p3,也就是说要得出p3信息则必须知道p1和p2的信息,这样才符合上面的定义 但是(p1)->p3,在这里p3只依赖主属性p1,p3并没有完全依赖于(p1,p3)候选码,则不符合上面的定义 ③:没有任何属性完全函数依赖于非码的任何一组属性示例1:现在有如下一张课程表属性为U = {Cno(课程编号), Cname(课程名称), Cdesc(课程说明)}①:它只有一个码Cno,没有任何属性(主/非主属性)对Cno产生部分函数依赖或传递函数依赖;--满足第三范式 ②:课程表中的Cno是唯一决定因素;--满足BCNF 如Cno可以决定Cname的值,Cno可以决定Cdesc的值;简化就是Cno->Cname,Cno->Cdesc -- 针对示例1分析是不是BCNF 判断是否为BCNF第一种方式,只需要把依赖关系都列出来如: Cno->Cname,Cno->Cdesc;只要箭头最左边是码(候选码,主码),那么就是BCNF 判断是否为BCNF第二种方式,只需要判断主属性内部是否存在部分函数依赖和传递函数依赖,如果不存在则是BCNF; 因为当前只要Cno主属性,则不可能存部分或者传递函数依赖示例2:现在有如下一张学生表属性为U ={Sno(学号), Sname(姓名), Sdept(专业), Sage(年龄)}假定Sname也具有唯一性,那么学生表就有两个码,分别为Sno(学号), Sname(姓名);这两个码都是由单个属性组成,彼此不相交。 ①:首先可以判断非主属性不存在对码的传递和部分依赖,则肯定满足第三范式; ②:学生表中除Sno,Sname外没有其它决定因素,所以学生表为BCNF; -- 针对示例2分析是不是BCNF 判断是否为BCNF第一种方式,只需要把依赖关系都列出来如: Sno->Sname,Sno->Sdept,Sno->Sdept,Sname->Sno,Sname->Sdept,Sname->Sdept; 只要箭头最左边是码(候选码,主码),那么就是BCNF 判断是否为BCNF第二种方式,只需要判断主属性内部是否存在部分函数依赖和传递函数依赖,如果不存在则是BCNF; 因为当前只要Sno,Sname主属性,则不可能存部分或者传递函数依赖示例3:现在有一张表SJP表属性为U={S(学生),J(课程),P(名次)}如上表关系:每一个学生选修每门门课程的成绩有一定的名次,每门课程中每一名次只有一个学生(即没有并列名次); 其中分析主属性(S,J,P), ①:由语义可得到函数依赖: (S,J)->P; (J,P)->S ②:(S,J)与(J,P)都可以作为候选码。 ③:关系模式中没有非主属性对码传递依赖或部分依赖,所以满足第三范式 ④:除(S,J)与(J,P)以外没有其它决定因素,所以为BCNF 判断是否为BCNF第一种方式,只需要把依赖关系都列出来如:(S,J)->P; (J,P)->S; 只要箭头最左边是码(候选码,主码),那么就是BCNF示例4:现在有一张表STJ表属性为U={S(学生),T(教师),J(课程)}如上表关系:每一教师只教一门课。每门课有若干教师,某一学生选定某门课,就对应一个固定的教师 其中分析主属性(S,J,P),候选码为(S,J), (S,T) ①:由语义可得到函数依赖: (S,J)->T, (S,T)->J, T->J (S,J)->T:通过学生和课程字段可以得出教师 (S,T)->J:通过学生和教师字段可以得出课程 T->J:因为每一教师只教一门课,所以通过教师可以得出课程 ②:关系模式中没有非主属性对码传递依赖或部分依赖,所以满足第三范式 ③:因为T是决定因素,而T不包含码,所以当前表不满足BCNF 判断是否为BCNF第一种方式,只需要把依赖关系都列出来如:(S,J)->T, (S,T)->J, T->J; 只要箭头最左边是码(候选码,主码),那么就是BCNF;但是当前案例中T不是具体的码(候选码),则不是BCNF针对示例4不是BCNF的关系模式,我们可以通过分解表成为BCNF:如:示例4的STJ表可以分解为:ST(S,T)与TJ(T,J),分解的这2张表都满足BCNF 拆分速记“谁跟你好,复制自己,把它带走”总结:3NF和BCNF是在函数依赖的条件下对模式分解所能达到的分离程度的测度。①:一个模式中的关系模式如果都属于BCNF,那么在函数依赖范畴内,它已实现了彻底的分离,已消除了插入和删除的异常 ②:3NF的“不彻底”性表现在可能存在主属性对码的部分函数依赖和传递函数依赖
.
关键词:
-
A Practical Methodology, HSM, Handler,Service,Model, for Golang Backend Developm
AsimplemethodologyordesignpatterncalledHSM(Handler,Service,Model)o
来源: 全球即时看!数据库三大范式(考试必备)
世界要闻:使用 JMX-Exporter 监控 Kafka 和 Zookeeper
A Practical Methodology, HSM, Handler,Service,Model, for Golang Backend Developm
【环球聚看点】直播源码搭建技术弹幕消息功能的实现
世界观热点:6月20日 11:03分 迈普医学(301033)股价快速拉升
日系还香吗?新一代本田皓影混动/插混上市:19.99万起要打比亚迪_世界报资讯
16.5亿打造!《封神三部曲》第一部7月20上映:预告片发布
全脂/低脂可选:特仑苏纯牛奶2.7元/盒大促(商超6元)
世界快看点丨微软明确不会涉足VR:市场实在太小
红魔8S Pro首发高频版骁龙8 Gen2!170万跑分比骁龙8 Gen3还猛 焦点速讯
【全球新要闻】对在建工程“全面体检”
全球新资讯:关于线性结构中的双向链表如何实现?
NCalc 学习笔记 (六)|天天观热点
也说一说IDEA热部署Web项目最终解决方案,确实大大提高工作效率
每日视点!详解在 Linux 启动时,如何自动执行命令或脚本
最资讯丨失乐园电影迅雷下载 失乐园电影未删减版迅雷下载
债市相对更强,股市估值处相对低位-焦点速递
墓地无人汽车探测到“鬼影”!真相到底是什么?
上海双层敞篷观光巴士将永久退役:已达13年强制报废标准 后继无车
首创双枪充电遥遥领先!比亚迪腾势N7首批量产车下线
高考过后 多所知名大学校长纷纷出镜招生|全球短讯
新买不到一个月特斯拉充电冒烟爆炸 女车主:很失望 产生心理阴影_天天动态
世界观点:菲律宾多方人士反对日本强推核污染水排海:不要污染我们的海洋
springboot~http请求头中如何放中文 当前快报
“泰坦尼克”号残骸观光潜艇氧气仅剩96小时 美加部署飞机搜寻
“全球第一吊”挑战191米最大陆上风力发电机 仅17分钟升至40层楼高
每日短讯:男子长城藏时间胶囊12年多人留纸条 网友直呼奇妙交流:很浪漫
屏摄电影被男子怒斥 影院称屏摄会对胶片有损伤 网友质疑:侮辱智商?-速讯
每日热门:美系开卷国产电动车!别克中大型轿跑E4上市:18.99万起
今日阵雨叨扰,周三周四阳光又将登场,抓紧洗晒! 环球热消息
【读财报】券商资管基金透视:财通、国泰君安资管年内收益领跑 中银证券业绩垫底 视讯
水电大省遭遇“水荒” 四川云南5月水电仍在下降
全球首例!杭州医生用5G帮5000公里外的新疆病人切除肝脏 画面网友惊叹
海口一特斯拉撞飞小车致一死一伤 现场视频被撞车360度旋转、有孩子被甩出-天天时快讯
电瓶车室内充电爆炸 墙都裂了 轮椅老人被吓得拔腿就跑 全球时讯
自救失败!“海航系”公司退市…
读发布!设计与部署稳定的分布式系统(第2版)笔记06_用户_世界观焦点
信息:手机可拆卸电池即将回归:利大于弊 别再被苹果牵着走
环球热资讯!回忆杀!高圆圆晒与贾静雯私照 梦回《倚天屠龙记》周芷若和赵敏
今日看点:早泄能治好吗?
100个物联网项目(基于ESP32)2快速入门
【linux命令】“瑞士军刀”nc的用法简介-天天关注
STL
马云指出淘宝天猫未来三个方向:回归淘宝、回归用户、回归互联网
花了1330万 还有600万只:巴黎向老鼠投降了 要“同居”_全球热点
冷清的618 焦虑的手机厂商:未来只能靠苹果创新了?
跳桥救人小哥引来女网友公开示爱:网友警告切勿炒作 世界热点评
中国男足亚运队1-0胜韩国U24队:孙沁涵抽射建功
美国能单挑全世界吗(美国军力全球第一敢于与世界敌么)
观焦点:登陆百度网盘错误 1550017 百度云同步盘登录失败155010
趋之若鹜的鹜什么意思_趋之若鹜
《王者荣耀》发布S32赛季漂泊之剑预告PV 两款战令皮肤奖励公布
韩国首尔教育厅将对学校供餐用水产品进行全面辐射检测 旨在保证食品安全
微信上线“安静模式” 专为有听力障碍的人创造更好的环境
《庆余年2》公布喜相逢版角色海报 增加一些重要新人物
JUC同步锁原理源码解析五----Phaser 今日热搜
ASP.NET Core MVC 从入门到精通之日志管理_世界热闻
计算几何之两条线段的交点|世界时快讯
看点:博客项目01
“狗狗嫌天热自己坐电梯回家”登上热搜 主人急里忙慌寻找
炒菜用什么油好?
车企卖衣服 不务正业? 焦点信息
微软Win11处理器要求变动:AMD、英特尔一大波新U加入支持
InnoDB 缓冲池
天天资讯:俄罗斯天然气工业银行拟参与无担保人民币债券市场
做小吃前途如何?惠记粉汤羊血加盟开店,开哪儿都火!
天天短讯!特斯拉车祸后复出 演员林志颖首次现身内地商演
专家称年轻人撑不起车市:中老年人才有足够能力拉动市场|视讯
今日精选:予以的拼音(予以)
【财经分析】数据赋能城市升级——2023中国资源型老工业城市转型发展指数研讨会在北京举办
每天喝咖啡的人 20年后都怎么样了?三大好处、三大不要 焦点精选
2024年见 龙芯也要做显卡了:IP设计已完成 还在优化
冷知识!大熊猫近视高达800度:只能看清几米之内物体 看热讯
索尼粉丝迷惑行为:请愿Xbox第一方游戏《星空》成PS5独占
开票!2023年安阳首场演唱会等你来抢!附购票入口
Liunx nginx服务|环球要闻
Manacher算法学习笔记
世界最新:799元价格屠夫!小米电视把国外品牌全打趴了
外来生物美国珍珠鳖被放生太湖:围观者欢呼雀跃|世界简讯
天天热讯:Mate发布Voicebox AI模型:仅需2秒片段即可“学会”语音细节
全球热资讯!首发4899元 外星人新款27英寸游戏显示器上架:180Hz高刷
国产操作系统赶超Win 10 统信UOS更新:换机可批量重装软件
世界头条:因编造、传播与期货交易有关的虚假信息行为 上海点钢电子商务被罚30万元
【环球热闻】Rust语言 - 接口设计的建议之显而易见(Obvious)
天猫品牌评估一般几天_天猫品牌评估_最新消息
北京电动自行车新规今起实施:电池温度达80度需有报警音
世界新消息丨女孩毕业典礼捐10万:含4年奖学金 用于帮助乡村孩子
当前观点:高通、联发科找到共同点了:骁龙8G3、天玑9300 AI性能爆发
云南普者黑现罕见的粉白相间荷花:花瓣如脂如玉 世界快播报
ppt讲课技巧互动_ppt讲课技巧 世界视点
【解决方法】锐捷 EVE 模拟器关联 Wireshark 进行抓包 焦点速讯
js-audio-recorder 插件实现web端录音
曼努埃尔·加西亚(关于曼努埃尔·加西亚介绍)
新加坡一廉价航班飞机降落后发现少个轮胎:曾出现胎压异常
全球领先!刘经南院士:北斗是唯一集通导遥等功能卫星导航系统 新视野
民营卫星俯拍四川盆地:中国两项唯一的天府之国 全球焦点
世界关注:达标没?调查称53.7%年轻人存款不足10万 感受下中等收入群体收入标准
海口一特斯拉高速行驶撞飞小车 官方通报:致一死一伤_当前独家
英雄联盟更新不动了怎么办_英雄联盟更新不动
【解决办法】DHCP Relay环境中PC无法获取IP地址,排错与解法 全球新要闻