1. 業務設計
1.1. 邏輯設計
1.1.1. 范式設計
1.1.1.1. 數據庫設計的第一大范式
數據庫表中的所有字段都只具有單一屬性
單一屬性的列是由基本數據類型所構成的
設計出來的表都是簡單的二維表
name-age列具有兩個屬性,一個name,一個 age不符合第一范式,把它拆分成兩列
1.1.1.2. 數據庫設計的第二大范式
要求表中只具有一個業務主鍵,也就是說符合第二范式的表不能存在非主鍵列只對部分主鍵的依賴關系
有兩張表:訂單表,產品表
一個訂單有多個產品,所以訂單的主鍵為【訂單ID】和【產品ID】組成的聯合主鍵,這樣2個組件不符合第二范式,而且產品ID和訂單ID沒有強關聯,故,把訂單表進行拆分為訂單表與訂單與商品的中間表
1.1.1.3. 數據庫設計的第三大范式
指每一個非非主屬性既不部分依賴於也不傳遞依賴於業務主鍵,也就是在第二范式的基礎上相處了非主鍵對主鍵的傳遞依賴
其中
客戶編號 和訂單編號管理 關聯
客戶姓名 和訂單編號管理 關聯
客戶編號 和 客戶姓名 關聯
如果客戶編號發生改變,用戶姓名也會改變,這樣不符合第三大范式,應該把客戶姓名這一列刪除
1.1.1.4. 范式設計實戰
按要求設計一個電子商務網站的數據庫結構
- 本網站只銷售圖書類產品
- 需要具備以下功能
用戶登陸 商品展示 供應商管理
用戶管理 商品管理 訂單銷售
1.1.1.4.1. 用戶登陸及用戶管理
只有一個業務主鍵,一定是符合第二范式
沒有屬性和業務主鍵存在傳遞依賴的關系,符合第三范式
1.1.1.4.2. 商品信息
一個商品可以屬於多個分類,故,商品名稱和分類應該是組合主鍵,會有大量冗余,不符合第二范式。應該把分類信息單獨存放
另外再建立一個中間表把分類信息和商品信息進行關聯
最后的三張表如下
1.1.1.4.3. 供應商管理功能
符合三大范式,不需要修改,但假如增加新的一列【銀行支行】,這樣隨着銀行賬戶的變化,銀行支行也會編號,不符合第三大范式
1.1.1.4.4. 在線銷售功能
有多個業務主鍵,不符合第二范式
訂單商品單價。訂單數量,訂單金額 存在傳遞依賴關系,不符合第三范式
拆分的結果如下
這時候,【訂單商品分類】與【訂單商品名】有依賴關聯,故合並如下
1.1.1.4.5. 表匯總
1.1.1.4.6. 根據范式設計引出的問題
編寫SQL查詢出每一個用戶的訂單總金額(用戶名,訂單總金額)
編寫SQL查詢出下單用戶和訂單詳情(訂單編號,用戶名,手機號,商品名稱,商品數量,商品價格)
問題:
大量的表關聯非常影響查詢的性能
完全符合范式化的設計有時並不能得到良好得SQL查詢性能
1.1.2. 反范式設計
1.1.2.1. 什么叫反范式化設計
l 反范式化是針對范式化而言得,在前面介紹了數據庫設計得范式
l 所謂得反范式化就是為了性能和讀取效率得考慮而適當得對數據庫設計范式得要求進行違反
l 允許存在少量得冗余,換句話來說反范式化就是使用空間來換取時間
1.1.2.1.1. 商品信息反范式設計
下面是范式設計的商品信息表
商品信息和分類信息經常一起查詢,所以把分類信息也放到商品表里面,冗余存放
1.1.2.1.2. 在線銷售功能反范式
下面是在線手寫功能的范式設計
首先來看訂單表
- 查詢訂單信息要關聯查詢到用戶表,但用戶表的電話是可能改變的,而且查詢訂單的時候經常查詢到用戶的電話
2. 查詢訂單經常會查詢到訂單金額,所以把訂單金額也冗余進來
新設計的訂單表如下
再來看訂單關聯表
- 和商品信息反范式設計一樣,查詢訂單的時候經常查詢商品分類,所以把商品分類和訂單名冗余進來
2.商品的單價可能會編號,如果關聯查詢查詢只能查詢到最新的商品價格,而查詢不到下訂單時候的價格,並且商品單價經常會查詢。 所以把訂單單價也冗余進來
新設計的商品關聯表如下
1.1.2.1.3. 反范式查詢
編寫SQL查詢出每一個用戶的訂單總金額
編寫SQL查詢出下單用戶和訂單詳情
1.1.3. 總結
不能完全按照范式得要求進行設計
考慮以后如何使用表
1.1.3.1. 范式化設計優缺點
優點:
可以盡量得減少數據冗余
范式化的更新操作比反范式化更快
范式化的表通常比反范式化的表更小
缺點:
對於查詢需要對多個表進行關聯
更難進行索引優化
1.1.3.2. 反范式化設計優缺點
優點:
可以減少表的關聯
可以更好的進行索引優化
缺點:
存在數據冗余及數據維護異常
對數據的修改需要更多的成本
1.2. 物理設計
1.2.1. 命名規范
1.2.1.0.1. 數據庫、表、字段的命名要遵守可讀性原則
使用大小寫來格式化的庫對象名字以獲得良好的可讀性
例如:使用custAddress而不是custaddress來提高可讀性。
1.2.1.0.2. 數據庫、表、字段的命名要遵守表意性原則
對象的名字應該能夠描述它所表示的對象
例如:
對於表,表的名稱應該能夠體現表中存儲的數據內容;對於存儲過程
存儲過程應該能夠體現存儲過程的功能。
1.2.1.0.3. 數據庫、表、字段的命名要遵守長名原則
盡可能少使用或者不使用縮寫
1.2.2. 存儲引擎選擇
1.2.3. 數據類型選擇
當一個列可以選擇多種數據類型時
l 優先考慮數字類型
l 其次是日期、時間類型
l 最后是字符類型
l 對於相同級別的數據類型,應該優先選擇占用空間小的數據類型
1.2.3.0.1. 浮點類型
注意float 和double 是非精度類型,如果是和金額相關盡量用decimal
select sum(c1),sum(c2),sum(c3) from test_numberic
1.2.3.0.2. 日期類型
面試經常問道 timestamp 類型 與 datetime區別
datetime類型在5.6中字段長度是5個字節
datetime類型在5.5中字段長度是8個字節
timestamp 和時區有關,而datetime無關
insert into test_time VALUES(NOW(),NOW(),NOW());
set time_zone="-10:00"