非正規化的資料庫規劃感想

1NF? 2NF? 3NF?
NF 是 Not Fine 還是 No Function?

如果資料庫規劃只想到正規化, 那就太小看資料庫了, 那還有什麼東西要考慮呢?



最近在改寫一個以前的案子, 幾年前已經套用過正規化的動作了, 但改起來就覺得不順手, 所以整理了一些元素, 簡單介紹一下:

1. 考慮系統用的編號:

因為系統用的編號與人用的編號是不同的, 常見的身分證字號雖然常被當 PK , 但畢竟是人設定的, "凡原則必有例外", 所以會有重複號, 無身分證號(外籍人士)等情況, 所以有些關連用的 PK , 應該考慮另編系統用的編號.

2. 考慮系統人員與使用者可以異動的欄位:

大概可以分成三種人用的(依需求可以再分)
a. 一定要系統人員設定, 屬於程式相關參數的.
b. 屬於管理人員可以異動, 但需要一定討論過的, 例如: 電話可以分不同類別, 或人的職業/學歷等.
c. 操作人員可以修改的項目.
為什麼會這樣區隔, 是因為覺得這樣的分類, 往往跟 Index 的建立有關連, 之後的速度也有差別.

3. 善用反正規化:

這應該很多資料都有提過, 透過程式先把一些資料, 另外存到某個欄位, 下次只要查詢該欄位, 就不用再查原始資料, 可以提高速度.

4. 使用節點而不用分層:

這是從地址分類想到的, 以前設計地址時, 是用分層處理, 例如個人資料有: 縣市 - 鄉鎮市區 兩欄, 系統資料則是"xx市-xx區"對照表, 後來把這種資料都列為節點, 例如: 台南市跟大安區都是"地理區"的一欄, 再有一欄"上層單位", 則縣市層級的資料就少很多, 維護也較方便.
原始:
106|台北縣|大安區|(誤)  
119|台北縣|風化區|(誤)  

如果要異動台北縣改為新北市, 就要全改, 所以後來架構改用
1|地球|0(無上層, 系統定義)  
2|臺灣|上層為1  
38(系統自動編碼)|台北縣|上層為2  
119(系統自動編碼)|風化區|上層為38  

這樣系統預設找上層為2(臺灣), 就是各縣市, 選好縣市, 再選區就可以了; 而且台北縣改名, 只要改一個欄位, 如果像台南縣與台南市合併, 只要把上層對照指標改掉就好.

5. 把一些同性質的東西擠在一起.

這是由通訊資料整理時想到的, 以前是"電話1", "電話2", "手機", 後來改用指標:
個人表: 個人編號, 姓名  
電話表: 電話編號, 電話號碼, 電話類型  
地址表: 地址編號, 最小單位區碼, 最小單位區碼對照地址, 其他地址, 地址類型  

考慮"電話"或"地址"這種"物件"其實可能會再異動(7碼升為8碼, 縣市升格), 所以將電話表與地址表獨立, 另外再用一張多對多的對照表來查詢.
當然開太多查詢表格會降低速度, 所以用了一個"反正規化", 地址有一項"最小單位區碼", 就是前面提到的分區, 系統記錄如果是 119 , 就會把"台北縣風化區"(誤)記在"最小單位區碼對照地址", 這樣只有新增或異動地址才會需要查詢區域對照表, 平常查地址時只要"個人""個人對照地址""地址". (其實實作時又有小調整)

6. 用同一張表打包起來:

因為剛剛的通訊資料分類法, 把一般常見的"表格式"通訊錄改掉了, 所以類別那一欄, 以前可能只有"公""私", 後來又多了"小三"(誤), "情婦"(大誤), "炮房"(18x), 但是這種類別在人事單位可能想調整, 所以就另外又設一張"類別表", 順便把最高學歷等東西都打包起來, 看起來像這樣
類型     |代號   |說明  
2(電話用)|33     |公  
2(電話用)|34     |小三  
4(地址用)|23     |通訊地址  
4(地址用)|28     |戶籍地址  
7(學歷用)|11     |低級大學  
7(學歷用)|14     |博士後研究助理(誤)  
1(職業用)|86     |水母(爆)  
1(職業用)|34     |遊民(再爆)  

這樣在對應的欄位, 比如要查學歷時, 只要查類別代號為 7 , 就知道最高學歷. 這樣也是結合使用頻率(啊, 忘記寫了), 因為異動學歷/職業通常是同時修改, 所以說明就可以放在同一張表, 而且使用機率不高, 所以程式異動也少.

大概簡單分類就這樣, 除了資料庫基本的正規化, 再加上一些"人"與"環境"的因素來整理的感想, 給大家參考看看.