數據庫設計
目的
結合DBMS(數據庫管理系統)實現有效存儲、高效訪問。減少數據冗餘,避免維護異常,節約存儲空間。
大概的步驟
需求分析->邏輯設計->物理設計(考慮數據庫系統的差異)->維護優化(新需求建表,索引,拆分)。
需求分析
理清楚實體及實體之間的關係(一對一,一對多,多對多),實體包含的屬性,哪些屬性(或者屬性組合)可以唯一標識一個實體
數據庫設計的三大範式
第一範式
如果數據庫表中的所有字段值都是不可分解的原子值,就說明該數據庫表滿足了第一範式。第一範式要求數據庫中的表都是二維表
就比如說,如果有一個表的列名是籍貫,裡面存儲的數據是廣東廣州等等,好了那麼這裡有一個問題,查詢的時候,我要怎麼查所有籍貫是廣東省的?或許可以用模糊查詢,但是這不是最好的解決辦法,如果是隻查廣東廣州呢?如果別的省份也有廣州呢?
所以說最好的解決辦法是把省份和城市分開。
第二範式
數據庫的表中不存在非關鍵字段對任意候選關鍵字段的部分函數依賴。
第二範式需要確保數據庫表中的每一列都和主鍵相關,而不能只與主鍵的某一部分相關(主要針對聯合主鍵而言)。也就是說在一個數據庫表中,一個表中只能保存一種數據,不可以把多種數據保存在同一張數據庫表中。
所有單關鍵字段的表都符合第二範式
對於某些多對多關係的表,需要分開存儲並且使用外鍵關聯。
第三範式
第三範式需要確保數據表中的每一列數據都和主鍵直接相關,而不能間接相關。
第二範式的基礎上解決了傳遞依賴
BC範式
在第三範式的基礎之上,數據庫表如果不存在任何字段對任意候選關鍵字段的傳遞函數依賴則符合BC範式。
確保數據表中的每一列數據都和主鍵和候選關鍵字直接相關,而不能間接相關
物理設計
MySQL存儲引擎
主流的有MyISAM和InnoDB
MyISAM
不支持事務處理,併發插入的表級鎖,一般不用於頻繁讀寫。
Innodb
MVCC行級鎖,適用於大部分情況。
表和字段命名規則
- 可讀性原則
使用大小寫,某些數據庫系統對大小寫敏感。
- 表意性原則
名稱應該表示功能
- 長名原則
儘量使用全名
字段類型的選擇原則
列的數據類型一方面影響了數據存儲空間的開銷,另一方面也會影響數據查詢性能。當一個列可以選擇多種數據類型的時候
- 首先考慮數字類型
- 其次考慮日期或者二進制類型
- 最後是字符類型
- 相同級別的數據應該優先選擇佔用空間小的,比如char varchar 之間應該選擇varchar
原因:
- 數據進行比較(查詢、JOIN、排序)時,相同數據,字符處理比數字慢
- 在數據庫中,數據處理以頁為單位,列的長度越小,利於性能提升。
char 和 varchar
1. 列中數據長度差不多的應該考慮char
2. 列中數據長度小於50 byte一般也用char。(列很少用除外,為了節省空間和減少IO,還是應該考慮varchar)
3. 一般不宜定義大於50 B的char
decimal和float
1. decimal(8個字節)存儲精確數據
2. float開銷小(4個字節)
時間類型
- int存儲
字段長度比datetime小,但是使用不方便,要函數轉換。只能存儲到2038-1-19。
- 時間粒度
考慮時間粒度選擇適合的類型值
主鍵選擇
1. 業務主鍵和數據庫主鍵
業務主鍵用於標識業務數據,進行表與表之間的關聯。
數據庫主鍵為了優化數據存儲
Innodb會默認生成6字節的隱含主鍵,所以儘量自定義主鍵提高存儲效率
2. 根據數據庫類型,考慮逐漸是否要順序增長
有些數據庫是按主鍵順序邏輯存儲的
3. 主鍵字段類型佔用空間要儘可能小。
對於使用聚集索引方式存儲的表,每個索引猴都會附加主鍵信息
避免使用外鍵約束
- 降低數據導入效率
- 增加維護成本‘
- 雖然不使用約束,但是相關聯的列上一定要建立索引
避免使用觸發器
- 降低數據導入效率
- 可能出現意想不到的數據異常
- 使業務邏輯變得複雜
關於預留字段
- 無法準確知道預留字段的類型
- 無法準確知道所存儲的內容
- 後期維護字段成本和增加字段成本相同
嚴禁使用預留字段
反範式化
通過數據冗餘增加存取效率,簡化查詢語句。空間換取時間。
- 減少關聯表數量
- 增加讀取效率
- 要適度
維護及優化
- 可以增加表或者字段的備註
- 經常查詢的列要加索引,索引不要包括太長的數據類型
- 過多的索引會降低讀和寫的效率,所以要定期維護索引碎片,SQL語句中不要使用強制索引關鍵字。
- 變更表結構控制表的寬度和大小,同時對數據字典進行維護
- 儘量不使用select *
- 控制用戶使用自定義函數
- 不要使用全局索引
表拆分
垂直拆分
- 經常查詢的列放到一起
- text, blob等大字段拆分到另一附加表中
水平拆分
- 通過主鍵哈希平均分成幾分
閱讀更多 im程序猿 的文章