ホームページ データベース 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 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Go 言語はデータベースの追加、削除、変更、クエリ操作をどのように実装しますか? Go 言語はデータベースの追加、削除、変更、クエリ操作をどのように実装しますか? Mar 27, 2024 pm 09:39 PM

Go 言語は、効率的かつ簡潔で習得が容易なプログラミング言語であり、同時プログラミングやネットワーク プログラミングに優れているため、開発者に好まれています。実際の開発ではデータベースの操作が欠かせませんが、今回はGo言語を使ってデータベースの追加・削除・変更・クエリ操作を実装する方法を紹介します。 Go 言語では、データベースを操作するために通常、よく使用される SQL パッケージや gorm などのサードパーティ ライブラリを使用します。ここでは SQL パッケージを例として、データベースの追加、削除、変更、クエリ操作を実装する方法を紹介します。 MySQL データベースを使用していると仮定します。

Hibernate はポリモーフィック マッピングをどのように実装しますか? Hibernate はポリモーフィック マッピングをどのように実装しますか? Apr 17, 2024 pm 12:09 PM

Hibernate ポリモーフィック マッピングは、継承されたクラスをデータベースにマップでき、次のマッピング タイプを提供します。 join-subclass: 親クラスのすべての列を含む、サブクラス用の別個のテーブルを作成します。 table-per-class: サブクラス固有の列のみを含む、サブクラス用の別個のテーブルを作成します。 Union-subclass: join-subclass と似ていますが、親クラス テーブルがすべてのサブクラス列を結合します。

iOS 18では、紛失または破損した写真を復元するための新しい「復元」アルバム機能が追加されます iOS 18では、紛失または破損した写真を復元するための新しい「復元」アルバム機能が追加されます Jul 18, 2024 am 05:48 AM

Apple の最新リリースの iOS18、iPadOS18、および macOS Sequoia システムでは、さまざまな理由で紛失または破損した写真やビデオをユーザーが簡単に回復できるように設計された重要な機能が写真アプリケーションに追加されました。この新機能では、写真アプリのツール セクションに「Recovered」というアルバムが導入され、ユーザーがデバイス上に写真ライブラリに含まれていない写真やビデオがある場合に自動的に表示されます。 「Recovered」アルバムの登場により、データベースの破損、カメラ アプリケーションが写真ライブラリに正しく保存されない、または写真ライブラリを管理するサードパーティ アプリケーションによって失われた写真やビデオに対する解決策が提供されます。ユーザーはいくつかの簡単な手順を実行するだけで済みます

HTML がデータベースを読み取る方法の詳細な分析 HTML がデータベースを読み取る方法の詳細な分析 Apr 09, 2024 pm 12:36 PM

HTML はデータベースを直接読み取ることはできませんが、JavaScript と AJAX を通じて実現できます。この手順には、データベース接続の確立、クエリの送信、応答の処理、ページの更新が含まれます。この記事では、JavaScript、AJAX、および PHP を使用して MySQL データベースからデータを読み取る実践的な例を示し、クエリ結果を HTML ページに動的に表示する方法を示します。この例では、XMLHttpRequest を使用してデータベース接続を確立し、クエリを送信して応答を処理することで、ページ要素にデータを埋め込み、データベースを読み取る HTML の機能を実現します。

PHP で MySQLi を使用してデータベース接続を確立するための詳細なチュートリアル PHP で MySQLi を使用してデータベース接続を確立するための詳細なチュートリアル Jun 04, 2024 pm 01:42 PM

MySQLi を使用して PHP でデータベース接続を確立する方法: MySQLi 拡張機能を含める (require_once) 接続関数を作成する (functionconnect_to_db) 接続関数を呼び出す ($conn=connect_to_db()) クエリを実行する ($result=$conn->query()) 閉じる接続 ( $conn->close())

PHP でデータベース接続エラーを処理する方法 PHP でデータベース接続エラーを処理する方法 Jun 05, 2024 pm 02:16 PM

PHP でデータベース接続エラーを処理するには、次の手順を使用できます。 mysqli_connect_errno() を使用してエラー コードを取得します。 mysqli_connect_error() を使用してエラー メッセージを取得します。これらのエラー メッセージをキャプチャしてログに記録することで、データベース接続の問題を簡単に特定して解決でき、アプリケーションをスムーズに実行できるようになります。

Samsung S24aiの機能を詳しく紹介 Samsung S24aiの機能を詳しく紹介 Jun 24, 2024 am 11:18 AM

2024 年は AI 携帯電話元年です。AI スマート テクノロジーにより、携帯電話はますます効率的かつ便利に使用できるようになります。最近、今年の初めにリリースされたGalaxy S24シリーズは、生成AIエクスペリエンスを再び改善しました。以下で詳細な機能の紹介を見てみましょう。 1. 生成 AI は Samsung Galaxy S24 シリーズを強力に強化します。Galaxy S24 シリーズは、Galaxy AI によって強化され、多くのインテリジェント アプリケーションをもたらします。これらの機能は Samsung One UI6.1 と緊密に統合されており、ユーザーはいつでも便利なインテリジェントなエクスペリエンスを得ることができ、パフォーマンスが大幅に向上します。携帯電話の効率と使いやすさ。 Galaxy S24 シリーズで先駆けて開発されたサークルアンド検索機能は、長押しするだけで実現できる機能です。

ドージコインとは ドージコインとは Apr 01, 2024 pm 04:46 PM

Dogecoin は、インターネット ミームに基づいて作成された暗号通貨であり、固定供給上限がなく、速い取引時間、低い取引手数料、そして大規模なミーム コミュニティを備えています。用途には、少額の取引、チップ、慈善寄付が含まれます。しかし、その無限の供給、市場のボラティリティ、ジョークコインとしての地位は、リスクと懸念ももたらします。ドージコインとは何ですか? Dogecoin は、インターネットのミームやジョークに基づいて作成された暗号通貨です。起源と歴史: Dogecoin は、2 人のソフトウェア エンジニア、ビリー マーカスとジャクソン パーマーによって 2013 年 12 月に作成されました。当時人気だった「Doge」ミームからインスピレーションを得た、片言の英語を話す柴犬をフィーチャーしたコミカルな写真。特徴と利点: 無制限の供給: ビットコインなどの他の暗号通貨とは異なります。

See all articles