數據結構設計的目的:
示例表:記錄每個學生所選課程信息,學號+課程名為主鍵
1、減少數據冗余,相同的不必要的數據在多個地方存在
如表中,多次出現學生姓名跟生日信息,課程學分都是冗余的
2、盡量避免數據維護中出現更新,插入和刪除異常
- 插入異常:如果表中的某個實體隨着另一個實體而存在,如表中需要插入一門課程,但是沒有學生選擇這門課,那么單獨插入課程名及課程其信息是會報錯的。
- 更新異常:如果更改表中的某個實體的單獨屬性時,需要對多行進行更新。如表中,需要更新數學這門課程的學分,會同時更新兩行,隨着選擇課程的學生變多,也會造成更多記錄的更新。
- 刪除異常:如果刪除表中的某一實體則會導致其他實體的消失。如表中,刪除數學課程,會刪除多條記錄
3、節約數據存儲空間
4、提高查詢效率
數據庫結構設計步驟:
- 需求分析:全面了解產品設計的存儲需求、數據處理需求、數據的安全性和完整性
- 邏輯設計:設計數據的邏輯存儲結構、數據實體之間的邏輯關系,解決數據冗余和數據維護異常
- 物理設計:根據所使用的的數據庫特點進行表結構設計
- 維護優化:根據實際情況對索引、存儲結構等進行優化
數據庫設計范式:
- 第一范式:數據庫表中的所有字段都只具有單一屬性,每一列都由基本的數據類型所構成,設計出來的表都是簡單的二維表。
- 第二范式:要求一個表中只具有一個業務主鍵,不能存在非主鍵列對部分主鍵的依賴關系。如表中主鍵學號+課程名,但學分與學號無直接依賴關系,所以只對課程名有依賴關系,不滿足第二范式。修改:單獨列一個學生信息表和課程信息表,選課表只需要關注學號與課程名的信息即可
- 第三范式:每一個非主屬性既不部分依賴也不傳遞依賴於業務主鍵,即在第二范式的基礎上消除了非主屬性對主鍵的傳遞依賴。
如下表:學生信息表
學號可以確定學生所在學院,那么學院信息又跟學生信息有了依賴關系,這就違反了第三范式。那么將學生信息表中只保留學院名稱,單獨創建一個學院信息表,存放學院信息,主鍵為學院名稱。這樣的話兩張表就符合了第三范式需求。
反范式化:
使用空間換取時間,為了性能和讀取效率的考慮適當的對數據庫設計范式的要求進行違反,允許存在少量的數據冗余
范式化設計的優缺點:
優點:可以盡量減少數據冗余、范式化的更新操作比反范式化快、范式化的表通常比反范式化更小
缺點:對於查詢需要關聯多個表、更難進行索引優化
反范式化設計優缺點:
優點:可以減少表的關聯、可以更好的進行索引優化
缺點:存在數據冗余及數據維護異常、對數據的修改需要更多的成本
物理設計:
根據所選擇的關系型數據庫的特點對邏輯模型進行存儲結構設計
內容:定義數據庫、表及字段的命名規范:遵循可讀性、表意性、長名性原則
選擇合適的存儲引擎:根據各引擎的適用性,根據場景選擇合適的存儲引擎
為表中的字段選擇合適的數據類型:當一個列可以選擇多種數據類型時,應該優先考慮數字類型,其次是日期或二進制類型,最后是字符類型。對於相同級別的數據類型,應該優先選擇占用空間小的數據類型
實數類型比較:
- FLOAT占4個字節,不是精確類型
- DOUBLE占8個字節,不是精確類型
- DECIMAL每4個字節存9個數字,小數點占一個字節。如:DECIMAL(18,9)需要9個字節來存儲
VARCHAR和CHAR類型:
VARCHAR和CHAR存儲空間是按字符並不是字節
VARCHAR類型的存儲特點:
- varchar用於存儲變長字符串,只占用必要的存儲空間
- 列的最大長度小於255則只占用一個額外字節用於記錄字符串長度
- 列的最大長度大於255則要占用兩個額外字節用於記錄字符串長度
VARCHAR長度選擇問題:
盡可能使用最小的符合需求的長度
varchar(5)和varchar(200)對於數據庫來說是根據實際數據長度去分配內存,但MySQL在內存中對字符的使用是固定寬度,列寬度太長會消耗更多的內存。
VARCHAR適用場景:
- 字符串列的最大長度比平均長度大很多
- 字符串列很少被更新
- 使用了多字節字符集存儲字符串
CHAR類型的存儲特點:
- CHAR類型是定長的
- 字符串存儲在CHAR類型的列中會刪除末尾的空格
- CHAR類型的最大寬度為255
CHAR類型的適用場景:
- CHAR類型適合存儲所長度近似的值
- CHAR類型適合存儲短字符串
- CHAR類型適合存儲經常更新的字符串列
日期數據類型:
DATATIME:
以YYYY-MM-DD HH:MM:SS[fraction]格式存儲日期時間。DATATIME類型與時區無關,占用8個字節的存儲空間。時間范圍1000-01-01 00:00:00到9999-12-31 23:59:59
datetime = YYYY-MM-DD HH:MM:SS
datetime(6) = YYYY-MM-DD HH:MM:SS.fraction
TIMESTAMP:
依賴於所指定的時區,在行的數據修改時可以自動修改timestamp列的值
date和time:
date類型用於保存1000-01-01到9999-12-31之間的日期
time類型用於存儲時間數據,格式為HH:MM:SS
date類型的優點:
- 占用的字節數比使用字符串、datetime, int存儲要少,使用date類型只需要3個字節
- 使用Date類型還可以利用日期時間函數進行日期之間的計算
存儲日期時間數據的注意事項:
- 不要使用字符串類型來存儲日期時間數據
- 日期時間類型通常比字符串占用的存儲空間小日期時間類型在進行查找過濾時可以利用日期來進行對比
- 日期時間類型還有着豐富的處理函數,可以方便的對時期類型進行日期計算
參考文獻:
- 高性能MySQL第三版
- 扛得住的MySQL數據庫架構:https://coding.imooc.com/class/chapter/49.html#Anchor