接下來我們來講解一下資料庫的正規化吧!
過去的資料庫主要是儲存資料的容器,只要有資料,就會不斷地被寫入其中。儘管資料庫設置了欄位和鍵值,隨著時間的推移,重複的資料仍然會不斷累積,導致在進行 CRUD 操作時變得不再方便。為了解決這個問題,我們需要對資料庫進行正規化處理。簡單來說,資料庫的正規化是通過消除重複資料來提高資料庫效能和管理便捷性的一種方法。
正規化有好幾階段,以下就來一一介紹。
第一正規化的目標是去除重複資料。此階段有三件要做的事情,分別為一個欄位儲存一項資料、刪除重複意義的欄位以及設定主鍵。
後面兩項應該很容易理解因此不贅述,而第一項的「一個欄位儲存一項資料」則是許多人時常忽略的點。舉例來說,如果是紀錄每個人購買品項的資料表,在品項那邊不應該再出現「牛奶、泡芙」這種內容,而是應該只寫一個品項、總共寫入兩筆資料才對。
(調整前)
(調整後)
第二正規化的目標是去除部分功能相依。
在完成第一正規化後,我們的資料表應該都有主鍵了,因此這個階段就是要確保每個欄位都要跟主鍵有直接關聯,將那些無關聯的欄位資料額外拉出去做新的表。
舉例來說,系上40位同學總共有5堂課可以搶(平均8人一堂課),我們可以將課堂本身的資料做成另外一張表。從另一個角度來說,如果其中一堂課的課程名稱有調整,那麼調整前的資料表就需要改8筆資料;相比之下,調整後的資料表僅需調整課程表上的名稱即可。
(調整前)
(調整後)
第三正規化的目標是去除遞移相依。
在確保每個欄位與主鍵的直接關聯性後,接下來我們需要確認除主鍵外的每個欄位之間是否有其他的關聯性。針對這些有關聯性欄位,可以考慮再拉出去做成新的表。
舉例來說,購買清單表中的數量與總金額有線性關係、課程資料表中老師姓名與老師辦公室之間也有直接關係等。
其實往後還有拓展到 6NF 以及其他的正規化種類,例如 BCNF、DK正規化等,不過實務上普遍僅會做到第三正規化就足夠使用了。正如一開始的介紹中提到的,正規化的目的是讓資料更易於管理與操作,因此只有當資料基數夠大時才需要去考慮正規化的深度;反之,如果資料本身不夠多,做太多正規化處理只會徒增資料庫的負擔(因為你可能更新一筆資料時要處理好幾張資料表)。
話說回來,我也曾經遇過資料基數不小(幾十萬筆)但是卻沒有做任何資料庫正規化的公司呢 XD