2018年10月14日 星期日

《面試官別再問》資料庫正規化(Normalization)

正規化說明

正規化是在資料庫中組織資料的程序。 其中包括建立資料表,以及在這些資料表之間根據規則建立關聯性,這些規則的設計目的是:透過刪除重複性和不一致的相依性,保護資料並讓資料庫更有彈性。


重複的資料會浪費磁碟空間,並產生維護方面的問題。 如果必須變更現有資料,並且該資料的位置超過一個以上,就必須在所有位置上以完全相同的方式進行變更。 如果資料只儲存於 [客戶] 資料表中,而不儲存於資料庫中任何其他位置,變更客戶地址就會更容易執行。 

何謂「不一致的相依性」? 使用者在 [客戶] 資料表中查找特定客戶的地址,確實是直覺反應,可是在 [客戶] 資料表中查找拜訪該客戶之員工的薪資,就沒有什麼道理了。 員工的薪資與該名員工相關,也就是所謂相依,因此應該移到 [員工] 資料表中。 不一致的相依性會讓資料難以存取,因為查找資料的路徑可能會遺失或中斷。 

資料庫正規化有一些規則。 每條規則都稱為「正規形式」。 如果遵守第一條規則,資料庫就稱為屬於「第一正規形式」。 如果遵守前三條規則,資料庫就被視為屬於「第三正規形式」。 雖然可能會有其他層級的正規形式,但第三正規形式被視為大部分應用程式所需的最高階正規形式。 

雖然有許多正式規則與規格,但真實情況不一定永遠完全都相同。 一般而言,正規化需要其他資料表,有些客戶也會嫌麻煩。 如果您決定違反正規化前三個原則中的其中一個原則,請確定您的應用程式能夠掌握所有可能發生的問題,例如重複的資料與不一致的相依性。 

下列說明包括範例。 

第一正規形式

  • 刪除各個資料表中的重複群組。
  • 為每一組關聯的資料建立不同的資料表。
  • 使用主索引鍵識別每一組關聯的資料。
不要在單一資料表中使用多重欄位儲存類似的資料。 例如,要追蹤來自兩個可能來源的存貨項目,存貨記錄會包含 [廠商代碼 1] 與 [廠商代碼 2] 欄位。 

當您增加第三個廠商時,會發生什麼狀況? 增加欄位並不能解決問題,增加欄位需要修改程式與資料表,而且無法順利納入數目不斷變動的廠商。 您應該採取另外一種作法,就是將所有廠商資料另外放置在不同的資料表中 (稱為 [廠商]),然後使用項目編號索引鍵,將存貨連結至廠商;或使用廠商代碼索引鍵將廠商連結至存貨。

第二正規形式

  • 為可套用於多筆記錄的多組值建立不同的資料表。
  • 使用外部索引鍵,讓這些資料表產生關聯。
記錄不應依賴資料表主索引鍵之外的索引鍵,但是必要時可使用複合索引鍵。 以會計系統中的客戶地址為例。 [客戶] 資料表需要地址,但 [訂單]、[送貨]、[發票]、[應收帳款] 與 [會計] 資料表也都需要地址。 不要將客戶地址儲存為這些資料表中的不同項目,而是儲存在一個位置,例如儲存在 [客戶] 資料表或另外一個 [地址] 資料表中。

第三正規形式

  • 刪除不依賴索引鍵的欄位。
記錄中的值如果不是該筆記錄之索引鍵的一部分,就不屬於資料表。 一般而言,只要欄位群組的內容可以套用至資料表中一筆以上的記錄時,您就可以考慮將這些欄位放置在不同的資料表中。 

例如,在 [員工招募] 資料表中,會包含某位求職者的學院名稱與地址。 但是您需要完整的學院清單,以整批寄送郵件。 如果學院資訊儲存在 [求職者] 資料表中,就無法列出不含目前求職者的學院清單。 因此,您應該要另外建立 [學院] 資料表,然後再使用學院代碼索引鍵連結至 [求職者] 資料表。 

例外狀況: 既要遵守第三正規形式,又要符合理論,實際上並不是永遠都行得通。 如果您有 [客戶] 資料表,並且想要刪除所有可能的欄位間相依性,則必須分別為城市、郵遞區號、銷售人員、客戶類別,以及其他可能會在多筆記錄中重複的因素,建立不同的資料表。 理論上,正規化值得追求。 但是太多小型資料表可能會降低效能,或超過可開啟的檔案與記憶體容量。


比較可行的方法是只針對變更頻繁的資料運用第三正規形式。 如果保留某些相依的欄位,請將應用程式設計為要求使用者在欄位變更時,驗證所有相關聯的欄位。

其他正規化形式

第四正規形式,也稱為「Boyce Codd 正規形式」(BCNF);而第五正規形式雖然存在,但實際設計時則很少考慮此形式。 漠視這些規則的結果可能無法設計出最完美的資料庫,但不會影響資料庫功能。


正規化處理規則 

規則一:刪除重複群組,為每一組相關的欄位建立個別的資料表,並且給 每一個資料表一個主鍵(1NF)。 
規則二:除去多餘資料,如果一個欄位只依照一個多值鍵值(Mutivalued Key) 的部份值,可將此欄位移至另一個資料表。例如:為確認一筆紀 錄而需填寫兩個欄位的話(例如員工代號,員工姓名),而這些欄位 只有一個需要放在此資料表,此類欄位需要建立一個新的資料表 (2NF)。 
規則三:除去與主鍵欄位無相依關係之欄位,如果一個欄位完全和索引鍵 沒有關聯,須此類欄位移至其他資料表(3NF)。 
規則四:隔離獨立的多重關係,沒有一個資料表可以包含數個一對多或多 對多之直接關係,例如一位員工具有多項技能,則必須將員工資 料和技能資料分別建在兩個不同的資料表(4NF)。 
規則五:隔離相關的多重關係,如果資料表內存在數個複雜的關係,那麼 必須將每項關係分別放在不同的資料表(5NF)。例如下述關係: 每個部門均有數筆設備 每種設備可能分由數個供應商提供 每個供應商可提供數種設備 每個部門有一份資格限制的供應商名單 

正規化範例資料表

下列步驟示範將虛構學生資料表正規化的程序。 
  1. 未正規化的資料表: 

    學號導師導師辦公室課程 1課程 2課程 3
    1022Jones412101-07143-01159-02
    4123Smith216201-01211-02214-01
  2. 第一正規形式: 沒有重複的群組

    資料表應該只有兩個維度。 因為一個學生會上數種課程,所以課程應該另列資料表。 因此,上述資料中的欄位 [課程 1]、[課程 2] 和 [課程 3] 即是設計問題所在。 

    試算表經常使用第三維度,但是資料表不應該使用第三維度。 另一個解決此問題的方式是使用一對多關聯性,不要將一邊與多邊放在相同的資料表中。 而是應該藉由刪除重複的群組 (課程 #),以第一正規形式建立另一個資料表,如下所示:

    學號導師導師辦公室課程 #
    1022Jones412101-07
    1022Jones412143-01
    1022Jones412159-02
    4123Smith216201-01
    4123Smith216211-02
    4123Smith216214-01
  3. 第二正規形式: 刪除重複的資料

    請注意上述資料表中,每個 [學號] 值都會配對多個 [課程 #] 值。 由於 [課程 #] 在運用時並不會依賴 [學號] (主索引鍵),因此這個關係並非第二正規形式。

    下列兩個資料表將示範第二正規形式: 

    學生:

    學號導師導師辦公室
    1022Jones412
    4123Smith216


    註冊課程:

    學號課程 #
    1022101-07
    1022143-01
    1022159-02
    4123201-01
    4123211-02
    4123214-01
  4. 第三正規形式: 刪除不依賴索引鍵的資料

    最後一個範例中,[導師辦公室] (導師的辦公室編號) 在運用時會依賴 [導師] 屬性。 而解決的方法,就是將該屬性從 [學生] 資料表移至 [教職員] 資料表,如下所示:

    學生:

    學號導師
    1022Jones
    4123Smith


    教職員:

    名稱辦公室部門
    Jones41242
    Smith21642

沒有留言:

張貼留言

網誌存檔