首頁 資料庫 mysql教程 数据库范式:掀起你的盖头来

数据库范式:掀起你的盖头来

Jun 07, 2016 pm 03:35 PM
介紹 資料庫 範式

【介绍】 凡是做过数据库设计的,只要不是大菜鸟,听到范式两个字,马上就会在脑海中浮现1NF,2NF,3NF,BCNF这些术语,但是若要大家详细的将这几个东东的专业定义描述出来。。。。。。呵呵,至少大部分人都会晕的,什么功能依赖、函数依赖,~!@#¥%……*

【介绍】
       凡是做过数据库设计的,只要不是大菜鸟,听到范式两个字,马上就会在脑海中浮现1NF,2NF,3NF,BCNF这些术语,但是若要大家详细的将这几个东东的专业定义描述出来。。。。。。呵呵,至少大部分人都会晕的,什么功能依赖、函数依赖,~!@#¥%……&*,my god!反正我是记不住:)

      但既然上了IT这条贼船,就无法避免和数据库设计打交道,丑媳妇总是要见公婆的:)既然无法避免,那就让我们勇敢的面对,揭开数据库范式的神秘面纱,看看到底是一个丑媳妇还是一个俊媳妇!!

【一句话范式】
       数据库范式本身的定义这里就不啰嗦了,大家随便上网搜索或者找本教材看看,保证随处可见,我在这里给大家用通俗的语言描述出来。

      在详细探讨之前还是啰嗦一句:千万要注意:范式只是在设计表的时候用的原则,数据库其它的设计例如索引、视图、触发器、存储过程等都和范式没有关系。

【第一范式1NF】
1NF在数据库设计中其实很简单:列不可再分
什么叫列不可再分呢?意思就是每一列只包含一个属性,所有属性的类型都是一样的。

      可能有人看到这里会说:晕,这还用说,谁设计的数据库表的列还可以再分呢?其实这句话只对了一部分,下面我们详细分析为什么叫只对了一部分。

      我们目前说的和用的数据库都是关系数据库,而关系数据库中是不可能设计一个列能够包含两个不同类型的属性的;但大千世界,无奇不有,除了关系数据库,还有其它的数据库,例如面向对象数据库、XML数据库,这种数据库就可以设计一个属性再包含多个子属,所以1NF在关系数据库中是天然满足的,而在其它类型数据库就不一定了。

      看了上面这段话,你是不是长吁一口气,心里踏实了,以为就可以从此不管1NF了呢?非也,数据库只做了第一层保证,但你还是可以设计不符合1NF的表来。下面我们给几个简单的例子,看看我们如何不遵守1NF。

例子1:Student表有一个属性name,类型为字符串。

      这个是最简单的例子,估计很多人都如此设计过,数据库也不会拒绝我们创建这样的表,但这个设计是不符合1NF的,为什么?很简单的,名字其实是“有名有姓”的,这其实就是两个属性。比如我们要查找姓“李”的同学有多少,或者查询同名(例如“狗剩”)的有哪些。这样的查询如果只有一个name列,呵呵,只能用like来查询了,这样不同的名字方式(例如中国人姓在前,美国人姓在后),like都需要修改,而且like还不能利用索引加快查询速度。

例子2:Custom表中有一个属性Address。

大家可以自己按照上面的例子自己分析一下,看看会有什么问题……..

=========== 我是分割线 =============

【第二范式2NF】
2NF可以如下描述:不存在属于部分主键的属性
什么情况下会出现属于部分主键的属性呢?这个没有通用的原则,我们只能举一个例子来说明。

      例如:成绩表Score主键是StudentID和CourseID,另外还有两个属性:一个是成绩Grade,一个是StudentName。这里的Grade就是完全由两个主键决定的(标准术语叫做“完全依赖”),而StudentName就只是StudentID的属性(标准术语叫做“部分依赖”),因此这个设计就不符合2NF。

      可能有人会问:那我就把StudentID作为主键可不可以?当然是可以的,但这样一来CourseID就又不符合2NF了,因为CourseID不是StudentID的属性。

说了半天了,都是说我们要遵守范式,但是不遵守范式究竟有什么问题呢?
简单的说就是两个问题:冗余(存储、操作)、异常(插不进、删多了)

(1)冗余
       一个学生选了很多课,这样StudentName就要重复很多次,因为重复很多次,所以哪天学生改名了,所有的StudentName记录都要更新。

(2)异常
插不进:刚来一个学生,还没有选课(假设所有的课都要选),那么他的StudentName就没有地方记录
删多了:假如学生毕业的,所有的课都学完了,那么所有的记录都删除,这样学生的名字最后也没有地方记录了。

【第三范式3NF】
3NF可以这样描述:属性不递归依赖于主键
       什么叫递归依赖呢?简单的就是"A → B → C",那么C就是递归依赖(所谓依赖,简单的讲就是“有关系”了)于A了。

注意:在数据库中,存在这样的关系要求A是主键、B和C不是主键。

下面还是给一个简单的例子:

      假定学生关系表为Student(学号, 姓名, 年龄, 所在学院, 学院地点, 学院电话),关键字为单一关键字"学号",因为存在如下决定关系:
  (学号) → (姓名, 年龄, 所在学院, 学院地点, 学院电话)
  这个数据库是符合2NF的,因为每个学生的这些信息都和学生本人是有关系的,也就是说由学号来决定,但是不符合3NF,因为存在如下关系:
  (学号) → (所在学院) → (学院地点, 学院电话)
  即存在非关键字段"学院地点"、"学院电话"对关键字段"学号"的递归依赖。
  它也会存在数据冗余、更新异常、插入异常和删除异常的情况,大家可以根据2NF样例中的分析方法分析。

【其它范式】
还有一堆其它范式:BCNF,甚至变态的4NF、5NF。

      但几乎所有的大侠、大虾、专家都说3NF就足够了,没有必要搞那么多了,所以我也就不想追究了,大家若有兴趣可以自己研究一下。
      

=========== 我是分割线 =============

【范式的两面:天使与魔鬼】
有人说:掌握了数据库范式你就是数据库设计高手了!!

      呵呵,成为高手看来也很简单的啊:)但此话对了一半,掌握数据库范式可以算一般高手,因为毕竟能够掌握范式并应用的人不算很多;但算不上高高手,为什么呢?因为范式不是万能的,也有自己的适应范围和局限性,如果到处不加原则和场合的使用,它很可能就是一个带给你梦魇的魔鬼!

首先我们看看数据库范式的目的是什么?范式的主要目的有三个:
  • 减少数据冗余
  • 优化表结构
  • 避免操作异常
       从以上三个目的我们可以看出,范式的主要作用是和数据存储有关的,它要解决的问题是数据存储的问题。为了解决这些问题,范式的最终动作其实就是将表拆分,将表拆成更多的表。

      但是我们在实际应用过程中,不可能把数据存起来就不管了,而是要存要取,否则存起来有什么意义呢:)既然要涉及到数据读取,那么数据读取的性能当然也是要重点关注的;另外,程序是人写的,对于人来说,表是否容易理解、是否容易使用,也是相当重要的。如果表的数量很多、关系太复杂,使用的时候很容易出错。下面我们看看范式在这两点上的限制。

范式的限制主要有如下几个:
  • 表数量增多会带来更多的连接查询,而连接查询的效率肯定比不上单表查询;
  • 表数量增多会导致表的关系复杂,SQL语句会更加难写,表的关系也会更加难理解;
       基于以上两个限制,数据库设计中还有一个概念叫做“反范式”,反范式很简单,从字面意思上理解即可,就是范式的反操作。下面是简单的对比:

------------范式------------------------------反范式----------------------
目的   解决存储问题                 解决性能问题和使用问题
动作   拆表                               合表
效果   存储优化                        性能优化
-------------------------------------------------------------------------------------

      看到这里,可能会有人问:那是不是没有范式就是性能最好的呢?非也,因为影响性能的除了连接查询外,还有一个关键因素就是“锁”,如果所有信息都在一张表里面,那么对这张表的所有操作之间的冲突会非常厉害,反而会导致性能急剧下降。

      因此,数据库设计最终应该是在“范式”和“反范式”之间进行权衡,找到最佳的平衡点,只有这样才是一个真正的数据库设计高手!!

      到此数据库范式的盖头已经被我们全部掀开,当然最后发现这既不是一个俊媳妇,也不是一个丑媳妇,只是一个可以和我们过设计日子的普普通通的媳妇而已:)


来源:http://blog.csdn.net/yunhua_lee/article/details/4030864

--------------------------------------------------------------------------

数据库范式是DBA必知必会的知识,但是很多半路出家的DBA确往往忽略了这部分知识。
eugene面试问应聘者时,爱问int(n)、varchar(n)这里N代表的含义,如果我面试应聘者,我肯定会问范式的相关问题。
为了不难住大家,下面我以一个game dba的角度给大家简单分享下我对范式的认识。

范式简介:
范式的英文名字叫 normal from,他是美国人E.F.Codd在上世纪70年代提出关系数据库模型后总结出来的,范式是关系数据库的理论基础。

要学习范式,我们先学习几个关于范式的术语,当然为了方便大家理解,这里只是列出了部分常用的术语,如果要完整深入的
学习,请查考相关数据库书籍。

实体:任何事物都是一个实体,对于游戏数据库来说,一个玩家是一个实体,一个游戏道具是一个实体。
属性:实体具有的某个特性,比如玩家的角色名,等级,性别等,通常属性可以看做表中的一列。
元组:表中的一行就是一个元组。
码:表中可以唯一确定一个行(元组)的某个属性或者属性组叫做码。这里的码一般就是数据库表中的唯一索引,一个表中可以有多个唯一索引,这些唯一索引统称候选码,如果从多个唯一索引中选一个出来作为主键,这个主键叫做主码。

有一些基础的术语知识后,我们来了解范式。
目前关系数据库有六种范式:第一范式、第二范式、第三范式、第四范式、第五范式、第六范式。
满足范式的要求是递增的,也就是要满足第二范式,必须先满足第一范式,要满足第三范式,必须先满足第二范式.类推…
由于第四范式、第五范式、第六范式总要是用于消除冗余数据,现在的存储空间已经比较充裕,并且适当冗余存储可以提高查询的效率,所以当前的数据库设计,一般满足前三个范式即可。

第一范式、无重复的列
这个范式是关系数据库的基本要求,如果不满足,那你的表就不是关系数据库。
要求:数据库中的每一列是具有原子性,不可以拆分的。

如果某个列变成了二叉树那样,那就不是关系数据库了。

第二范式、属性
要求:所有属性完全依耐于主码,消除非候选码对主码的部分函数依耐。
通俗理解:所有属性完全依耐于主键,消除非主属性对主键的部分函数依耐。
通过一个玩家和家族关系的表来说明吧。

CREATE TABLE `family` (
  `userid` varchar(34) NOT NULL DEFAULT '',
  `familyid` int(11) NOT NULL DEFAULT '0',
  `familyname` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`userid`,`familyid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
登入後複製

userid 玩家id
familyid 家族id
familyname 家族名
现在familyname其实只应依耐familyid,对(userid,familyid)这个组合主键存在部分依耐关系。
这样的表会出现哪些问题呢?

1、系统创建一个家族,userid的值为null,可以插入吗? 不可以,插入异常了。
有人说:让userid default null,你试试看。还有人说:设定一个系统使用的userid,当然可以,但这不是我们讨论的内容。
2、当一个家族有很多人加入以后,这个家族的名字存储了很多次 数据冗余了
3、当一个家族有很多人加入以后,需要修改一下家族名字? 会修改多少条记录?更新异常了
4、当所有人退出家族后,想要保留家族的存在?可以吗? 不可以,删除异常了

如何解决这个问题?
一般这种分体通过拆表就可以了,将上面的一个表改成下面的两个表,这样问题就都解决了。

CREATE TABLE `family3` (
  `userid` varchar(34) NOT NULL,
  `familyid` int(11) DEFAULT NULL,
  PRIMARY KEY (`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

CREATE TABLE `family4` (
  `familyid` int(11) NOT NULL DEFAULT '0',
  `familyname` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`familyid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
登入後複製

第三范式、属性
要求:不依耐于其他非组属性,消除传递依耐。
这个咱也用刚才那个表,稍微改一下,把组合主键改成了userid为主键。

CREATE TABLE `family` (
  `userid` varchar(34) NOT NULL DEFAULT '',
  `familyid` int(11) DEFAULT NULL,
  `familyname` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
登入後複製

现在familyname其实只应依耐familyid,对userid这个主键存在传递依耐关系。
会出现的问题和范式二一样。解决方法也和范式二一样。

来源:http://isadba.com/?p=261


2nf意思是,父亲姓什么,儿子就姓什么
3nf的意思是,孙子的姓是跟父亲一样就行了,虽然孙子也跟爷爷的姓也是一样的,但这是由于父亲跟爷爷的姓一样带来的(2nf),而不需要专门说孙子的姓要跟爷爷一样;如果有人说孙子的姓要跟爷爷一样,这就相当于违反了3nf,因为在2nf中已经确定了这一点

来源:http://www.itpub.net/thread-1493555-3-1.html

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
威爾R.E.P.O.有交叉遊戲嗎?
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Hibernate 如何實作多型映射? Hibernate 如何實作多型映射? Apr 17, 2024 pm 12:09 PM

Hibernate多態映射可映射繼承類別到資料庫,提供以下映射類型:joined-subclass:為子類別建立單獨表,包含父類別所有欄位。 table-per-class:為子類別建立單獨資料表,僅包含子類別特有列。 union-subclass:類似joined-subclass,但父類別表聯合所有子類別列。

iOS 18 新增「已復原」相簿功能 可找回遺失或損壞的照片 iOS 18 新增「已復原」相簿功能 可找回遺失或損壞的照片 Jul 18, 2024 am 05:48 AM

蘋果公司最新發布的iOS18、iPadOS18以及macOSSequoia系統為Photos應用程式增添了一項重要功能,旨在幫助用戶輕鬆恢復因各種原因遺失或損壞的照片和影片。這項新功能在Photos應用的"工具"部分引入了一個名為"已恢復"的相冊,當用戶設備中存在未納入其照片庫的圖片或影片時,該相冊將自動顯示。 "已恢復"相簿的出現為因資料庫損壞、相機應用未正確保存至照片庫或第三方應用管理照片庫時照片和視頻丟失提供了解決方案。使用者只需簡單幾步

在PHP中使用MySQLi建立資料庫連線的詳盡教學 在PHP中使用MySQLi建立資料庫連線的詳盡教學 Jun 04, 2024 pm 01:42 PM

如何在PHP中使用MySQLi建立資料庫連線:包含MySQLi擴充(require_once)建立連線函數(functionconnect_to_db)呼叫連線函數($conn=connect_to_db())執行查詢($result=$conn->query())關閉連線( $conn->close())

深入解析HTML如何讀取資料庫 深入解析HTML如何讀取資料庫 Apr 09, 2024 pm 12:36 PM

HTML無法直接讀取資料庫,但可以透過JavaScript和AJAX實作。其步驟包括建立資料庫連線、發送查詢、處理回應和更新頁面。本文提供了利用JavaScript、AJAX和PHP來從MySQL資料庫讀取資料的實戰範例,展示如何在HTML頁面中動態顯示查詢結果。此範例使用XMLHttpRequest建立資料庫連接,發送查詢並處理回應,從而將資料填入頁面元素中,實現了HTML讀取資料庫的功能。

如何在PHP中處理資料庫連線錯誤 如何在PHP中處理資料庫連線錯誤 Jun 05, 2024 pm 02:16 PM

PHP處理資料庫連線報錯,可以使用下列步驟:使用mysqli_connect_errno()取得錯誤代碼。使用mysqli_connect_error()取得錯誤訊息。透過擷取並記錄這些錯誤訊息,可以輕鬆識別並解決資料庫連接問題,確保應用程式的順暢運作。

什麼是狗狗幣 什麼是狗狗幣 Apr 01, 2024 pm 04:46 PM

狗狗幣是一種基於網路迷因創建的加密貨幣,沒有固定的供應上限,交易時間快速,交易費用低,擁有龐大的迷因社群。用途包括小額交易、打賞和慈善捐贈。然而,其無限供應量、市場波動和作為笑話幣的地位也帶來風險和擔憂。什麼是狗狗幣?狗狗幣是一種基於網路迷因和笑話創建的加密貨幣。起源與歷史:2013年12月,兩位軟體工程師BillyMarkus和JacksonPalmer創立狗狗幣。靈感來自於當時流行的"Doge"模因,一個以一隻柴犬為特徵的滑稽照片加上破碎英語。特徵與優勢:無限供應量:與比特幣等其他加密貨

三星S24ai功能詳細介紹 三星S24ai功能詳細介紹 Jun 24, 2024 am 11:18 AM

2024是AI手机的元年,越来越多的手机集成了多项ai功能,通过ai智能技术的赋能,让我们的手机使用更加高效便捷。近日,年初发布的GalaxyS24系列再度提升了其生成式AI的体验,下面下详细的功能介绍,一起来看看吧。一、生成式AI深度赋能三星GalaxyS24系列通过GalaxyAI的赋能,带来了诸多智能化应用,这些功能与SamsungOneUI6.1深度集成,让用户可以随时获得便利的智能体验,显著提升了手机的使用效率和便捷性。由GalaxyS24系列首创的即圈即搜功能是亮点之一,用户只需长按

霓虹深淵第八色武器介紹 霓虹深淵第八色武器介紹 Mar 31, 2024 pm 03:51 PM

第八色是霓虹深淵中的一把武器,很多的玩家都想了解一下關於武器第八色額彈道、武器強度好玩法這些內容。那麼下面就讓我們一起來看看霓虹深淵第八色武器彈道、武器強度、武器玩法詳細攻略吧。霓虹深淵第八色詳細攻略武器介紹:巫師的秘密武器!武器攻速:正常武器強度:適中武器玩法:第八色的攻擊方式為三次單體攻擊然後發射一道射線。彈道展示:

See all articles