本文討論關(guān)系數(shù)據(jù)庫(kù)設(shè)計(jì)相關(guān)的一些內(nèi)容,涉及關(guān)系模型,表結(jié)構(gòu)設(shè)計(jì)等內(nèi)容,以學(xué)生選修課程講述設(shè)計(jì)過(guò)程,在盡量講清楚設(shè)計(jì)要領(lǐng)的前提下,簡(jiǎn)化設(shè)計(jì)內(nèi)容。
本文基于MySQL數(shù)據(jù)庫(kù)為基礎(chǔ),適合有一定關(guān)系型數(shù)據(jù)庫(kù)基礎(chǔ)的人閱讀。
實(shí)體-關(guān)系模型(E-R)首先搞清楚什么是E-R數(shù)據(jù)模型?它有什么用?
E-R模型在將現(xiàn)實(shí)世界中事實(shí)的含義和相互關(guān)聯(lián)映射到概念模式方面非常有用,因此,許多數(shù)據(jù)庫(kù)設(shè)計(jì)工具都利用了E-R模型的概念。E-R模型所采用的三個(gè)主要概念是:實(shí)體集、關(guān)系集和屬性。
實(shí)體:實(shí)體是世界中可以區(qū)別于其他對(duì)象的“事件”或者“物體”,例如,學(xué)校里的每個(gè)學(xué)生、學(xué)生選修的每門課程等都是一個(gè)實(shí)體。
屬性:屬性是實(shí)體集中每個(gè)成員具有的描述性性質(zhì)。例如,學(xué)生的姓名,學(xué)號(hào)等。
實(shí)體集:實(shí)體集就是就有相同類型及屬性的實(shí)體集合,比如,學(xué)校里的所有學(xué)生,學(xué)生選修的所有課程等。
關(guān)系:關(guān)系是多個(gè)實(shí)體間的相互關(guān)聯(lián)。例如,小明選修語(yǔ)文課程。
關(guān)系集:關(guān)系集是同類關(guān)系的集合。例如,所用學(xué)生選修課程的集合。
其中,(學(xué)號(hào),姓名,年齡,性別)為學(xué)生的屬性,(成績(jī))為選修關(guān)系的屬性,(課程號(hào),課程名,學(xué)分)為課程的屬性。學(xué)生和課程之間的關(guān)系是多對(duì)多,即一個(gè)學(xué)生可以選擇多門課程,一門課程可以被多個(gè)學(xué)生選修。
關(guān)系表設(shè)計(jì)從上面的E-R圖,我們一眼就能看出他們之間的聯(lián)系,那該如何設(shè)計(jì)關(guān)系模式呢?
我們要知道,關(guān)系數(shù)據(jù)庫(kù)設(shè)計(jì)的目的是為了生成一組關(guān)系模式,使我們能夠既不必存儲(chǔ)不必要的冗余信息,又能方便地獲取信息。為了是我們方便的達(dá)到這個(gè)目的,范式設(shè)計(jì)應(yīng)運(yùn)而生。
Boyce-Codd范式
我們所知道的令人滿意的范式之一是Boyce-Codd范式(BCNF)。如果對(duì)F+中所有形如 α→β 的函數(shù)依賴,其中 α?R 且 β?R,下面的定義至少有一個(gè)成立:
α→β 是平凡函數(shù)依賴(即 β ? α)。(一般來(lái)說(shuō),平凡函數(shù)依賴并沒有討論意義,討論的都是非平凡函數(shù)依賴,即 β ?? α 的情況)
α 是模式R的超碼。
考慮如下關(guān)系模式及其相應(yīng)的函數(shù)依賴:
學(xué)生 = (學(xué)號(hào),姓名,年齡,性別)
學(xué)號(hào) → 姓名 年齡 性別
課程 = (課程號(hào),課程名,學(xué)分)
課程號(hào) → 課程名 學(xué)分
選修 = (學(xué)號(hào),課程號(hào),成績(jī))
學(xué)號(hào) 課程號(hào) → 成績(jī)
以上模式均屬于BCNF。就拿第一組關(guān)系模式來(lái)說(shuō),學(xué)生上僅有的非平凡函數(shù)依賴,箭頭左側(cè)是學(xué)號(hào),學(xué)號(hào)是該模式的一個(gè)候選碼(候選碼屬于超碼的子集),沒有破壞BCNF的定義。
其實(shí)并不是每個(gè)BCNF都能保持函數(shù)依賴的,例如:
Banker-schema = (branch-name,customer-name,banker-name)
它表示的是一個(gè)客戶在某一分支機(jī)構(gòu)有一個(gè)銀行賬戶負(fù)責(zé)人。它要求滿足的函數(shù)依賴集F為
banker-name → branch-name
branch-name customer-name → banker-name
顯然,Banker-schema不屬于BCNF,因?yàn)?banker-name 不是超碼。
我們可以將它分解得到如下的BCNF:
Banker-branch-schema = (banker-name,branch-name)
Customer-banker-schema = (customer-name,banker-name)
分解后的模式只保持了banker-name → branch-name,而branch-name customer-name → banker-name的依賴沒有保持。
第三范式
當(dāng)我們不能同時(shí)滿足以下三個(gè)設(shè)計(jì)目標(biāo):
BCNF。
無(wú)損連接。
保持函數(shù)依賴。
我們可以放棄BCNF而接受相對(duì)較弱的第三范式(3NF)。因?yàn)?NF總能找到無(wú)損連接并保持依賴的分解。
具有函數(shù)依賴即F的關(guān)系模式R屬于3NF,只要F+中所有形如 α→β 的函數(shù)依賴,其中 α?R 且 β?R,下面的定義至少有一個(gè)成立:
α→β 是平凡函數(shù)依賴(即 β ? α)。
α 是模式R的超碼。
β - α 中的每個(gè)屬性 A 都包含在R的候選碼中。
回到Banker-schema的例子中,我們已經(jīng)看到了沒能將該關(guān)系模式轉(zhuǎn)化成BCNF而又保持依賴和無(wú)損連接的分解,但改模式屬于3NF。在Banker-schema中,候選碼是{branch-name,customer-name},所以Banker-schema上不包含候選碼的就只有banker-name。
而形如 α → banker-name 的非平凡函數(shù)依賴都是以{branch-name,customer-name}作為 α 的一部分。由于{branch-name,customer-name}是候選碼,所以符合3NF的定義。
每個(gè)BCNF都屬于3NF,因?yàn)锽CNF的約束比3NF更嚴(yán)格。
存儲(chǔ)引擎的選擇關(guān)系模式一但確定,基本的數(shù)據(jù)庫(kù)表結(jié)構(gòu)就確定了,接下來(lái)就是表結(jié)構(gòu)的詳細(xì)設(shè)計(jì)了,這里先從存儲(chǔ)引擎開始,MySQL提供的各種存儲(chǔ)引擎都是根據(jù)不同的用例設(shè)計(jì)的。
最常用的兩種存儲(chǔ)引擎:MyISAM和InnoDB。
MyISAM:MySQL 5.5.5以前,MyISAM作為MySQL的默認(rèn)存儲(chǔ)引擎。
InnoDB:MySQL 5.5.5以后,InnoDB作為MySQL的默認(rèn)存儲(chǔ)引擎。
何如選擇?
選擇標(biāo)準(zhǔn): 根據(jù)應(yīng)用特點(diǎn)選擇合適的存儲(chǔ)引擎,對(duì)于復(fù)雜的應(yīng)用系統(tǒng)可以根據(jù)實(shí)際情況選擇多種存儲(chǔ)引擎進(jìn)行組合。但是要知道組合使用的缺點(diǎn):
InnoDB和非InnoDB存儲(chǔ)引擎的組合對(duì)比,僅使用InnoDB存儲(chǔ)引擎可以簡(jiǎn)化備份和恢復(fù)操作。MySQL Enterprise Backup對(duì)使用InnoDB存儲(chǔ)引擎的所有表進(jìn)行熱備份。對(duì)于使用MyISAM或其他非InnoDB存儲(chǔ)引擎的表,它會(huì)執(zhí)行“熱”備份,數(shù)據(jù)庫(kù)會(huì)繼續(xù)運(yùn)行,但這些表在備份時(shí)不能修改。
下面是常用存儲(chǔ)引擎的適用環(huán)境:
InnoDB:事務(wù)型業(yè)務(wù)場(chǎng)景首選。
MyISAM:非事務(wù)型的大多數(shù)業(yè)務(wù)場(chǎng)景。
Memory:數(shù)據(jù)保存到內(nèi)存中,能提供極速的訪問(wèn)速度。(個(gè)人覺得可以使用Redis等NoSQL數(shù)據(jù)庫(kù)代替)
字符集選擇存儲(chǔ)引擎之后就是確定字符集,字符集的選擇十分重要,不管是MySQL還是Oracle,如果在數(shù)據(jù)庫(kù)創(chuàng)建階段沒有正確選擇字符集,那么在后期需要更換字符集的時(shí)候?qū)⒁冻龈甙旱拇鷥r(jià)。
如何選擇?
建議在能夠完全滿足應(yīng)用當(dāng)下和未來(lái)幾年發(fā)展的前提下,盡量使用小的字符集。應(yīng)為更小的字符集意味著能夠節(jié)省空間、減少網(wǎng)絡(luò)傳輸字節(jié)數(shù),同時(shí)由于存儲(chǔ)空間小間接的提升了系統(tǒng)的性能。
不同的數(shù)據(jù)庫(kù)有不同的字符集應(yīng)用級(jí)別,分別為服務(wù)器級(jí)別、庫(kù)級(jí)別、表級(jí)別、字段級(jí)別,通常推薦使用庫(kù)級(jí)別或者表級(jí)別。因?yàn)閹?kù)級(jí)別或者表級(jí)別在保有靈活性的同時(shí),兼顧數(shù)據(jù)間字符集的統(tǒng)一,這可以給開發(fā)省去很多處理字符集的麻煩。
數(shù)據(jù)類型的選擇選擇原則
前提:使用合適的存儲(chǔ)引擎。
選擇原則:為了獲得最佳的存儲(chǔ),您應(yīng)該在所有情況下嘗試使用最精確的類型。
固定長(zhǎng)度和可變長(zhǎng)度
char 與 varchar
請(qǐng)注意上表中最后一行的值只適用不使用嚴(yán)格模式時(shí);如果 MySQL 運(yùn)行在嚴(yán)格模式,超過(guò)列 長(zhǎng)度的值不保存,并且會(huì)出現(xiàn)錯(cuò)誤。
從 CHAR(4)和 VARCHAR(4)列檢索的值并不總是相同,因?yàn)闄z索時(shí)從 CHAR 列刪除了尾部的空 格。通過(guò)下面的例子說(shuō)明該差別:
mysql》 CREATE TABLE vc (v VARCHAR(4), c CHAR(4));
Query OK, 0 rows affected (0.01 sec)
mysql》 INSERT INTO vc VALUES (‘a(chǎn)b ’, ‘a(chǎn)b ’);
Query OK, 1 row affected (0.00 sec)
mysql》 SELECT CONCAT(‘(’, v, ‘)’), CONCAT(‘(’, c, ‘)’) FROM vc;
+---------------------+---------------------+
| CONCAT(‘(’, v, ‘)’) | CONCAT(‘(’, c, ‘)’) |
+---------------------+---------------------+
| (ab ) | (ab) |
+---------------------+---------------------+
1 row in set (0.06 sec)
對(duì)于InnoDB數(shù)據(jù)表,內(nèi)部的行格式?jīng)]有區(qū)分固定長(zhǎng)度和可變長(zhǎng)度列,所有數(shù)據(jù)化行都使用指向數(shù)據(jù)列值的頭指針,因此在本質(zhì)上,使用固定長(zhǎng)度的CHAR列不一定比使用可變長(zhǎng)度的VARCHAR列要好。
因?yàn)?,主要的性能因?shù)是數(shù)據(jù)行使用的存儲(chǔ)總量。對(duì)于占用空間來(lái)說(shuō),CHAR總是大于等于VARCHAR,所以,使用VARCHAR來(lái)最小化行數(shù)據(jù)的存儲(chǔ)總量,進(jìn)而減少磁盤I/O頻率。
text 和 blob
在使用text或者blob類型的字段是需要注意一下幾點(diǎn),以便獲得更好的性能:
執(zhí)行大量的刪除和更新操作后,會(huì)留下很”空洞“,需要定期optimize table進(jìn)行碎片整理;
避免查詢大型的text和blob。查詢大型的text和blob會(huì)使一頁(yè)能裝下的數(shù)據(jù)量減少,增加磁盤I/O壓力。
把text和blob分離到單獨(dú)的表中。這會(huì)把原來(lái)表中的數(shù)據(jù)列轉(zhuǎn)變?yōu)楦痰墓潭ㄩL(zhǎng)度的數(shù)據(jù)行格式,這個(gè)十分有用。
浮點(diǎn)數(shù)和定點(diǎn)數(shù)
在MySQL中float、double是浮點(diǎn)數(shù),decimal是定點(diǎn)數(shù)。
浮點(diǎn)數(shù)優(yōu)勢(shì):在長(zhǎng)度一定的情況下,浮點(diǎn)數(shù)能表示更大的數(shù)據(jù)范圍。
浮點(diǎn)數(shù)缺點(diǎn):精度問(wèn)題。
友情提醒:在有關(guān)金錢交易方面浮點(diǎn)數(shù)慎用?。?!
整數(shù)
MySQL支持SQL標(biāo)準(zhǔn)整數(shù)類型INTEGER(或INT)和SMALLINT。作為標(biāo)準(zhǔn)的擴(kuò)展,MySQL還支持整數(shù)類型TINYINT、MEDIUMINT和BIGINT。下表顯示了每個(gè)整數(shù)類型所需的存儲(chǔ)空間和范圍。
索引設(shè)計(jì)設(shè)計(jì)原則
搜索的索引列,不一定是所要選擇的列。最適合索引的列是出現(xiàn)在 WHERE 子 句中的列,或連接子句中指定的列,而不是出現(xiàn)在 SELECT 關(guān)鍵字后的選擇列表中的列。
使用惟一索引。對(duì)于惟一值的列,索引的效果最好,而具有多個(gè) 重復(fù)值的列,其索引效果最差。
使用短索引。如果對(duì)字符串列進(jìn)行索引,應(yīng)該指定一個(gè)前綴長(zhǎng)度 。例如,如果有一個(gè) CHAR(200) 列,如果在前 10 個(gè)或 20 個(gè)字符內(nèi),多數(shù)值是惟一的, 那么就不要對(duì)整個(gè)列進(jìn)行索引。
利用最左前綴。每個(gè)額外的索 引都要占用額外的磁盤空間,并降低寫操作的性能。
不要過(guò)度索引。
考慮在列上進(jìn)行的比較類型。如果是在列上做函數(shù)運(yùn)算,對(duì)其進(jìn)行索引將毫無(wú)意義。
Student中姓名的長(zhǎng)度是40,這里把外國(guó)人也考慮進(jìn)來(lái)了;
Student中性別定義成枚舉,主要是枚舉意義簡(jiǎn)明;
Student中沒有存年齡,而存儲(chǔ)的出生日期,是因?yàn)槟挲g并不是一成不變的,并且能夠通過(guò)出生日期正確計(jì)算。
SC中成績(jī)使用的是double而不采用decimal,主要是因?yàn)槌煽?jī)并不需要那么高的精確度。
SC中(sno,cno)作為聯(lián)合主鍵而不是獨(dú)立主鍵,由于現(xiàn)階段markdown無(wú)法合拼行,所以無(wú)法編輯。
參考(美)Abraham Silberschatz等。數(shù)據(jù)庫(kù)系統(tǒng)概念。北京:機(jī)械工業(yè)出版社,2012
MySQL 5.7 Reference Manual
[eimhe.com]網(wǎng)易技術(shù)部的MySQL中文資料。
(感謝閱讀,希望對(duì)你所有幫助)來(lái)源:blog.csdn.net/qq_36011946/article/details/105305063
編輯:jq
-
數(shù)據(jù)庫(kù)
+關(guān)注
關(guān)注
7文章
3842瀏覽量
64562
原文標(biāo)題:如何設(shè)計(jì)關(guān)系型數(shù)據(jù)庫(kù)?
文章出處:【微信號(hào):harmonyos_developer,微信公眾號(hào):harmonyos_developer】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論