--- title: '什麽是正規化?' --- 什麽是正規化? === 正規化(Normalization)是數據庫設計中的一個重要過程,它涉及將數據庫中的數據結構安排到一組特定的規則和格式中。這樣做的目的是減少數據重複和依賴,並提高數據庫的效率和可擴展性。 為什麽要資料正規化? --- 1. 減少數據重複: - 重複的數據可能會導致不一致性,正規化通過將重複數據分解到不同的表中來解決這一問題。 2. 提高查詢效率: - 適當的正規化可以讓查詢更快,因為數據庫不需要搜尋重複的數據。 3. 易於維護: - 正規化的數據庫更易於維護和更新。 正規化的階段 --- 1. 第一范式 (1NF): - 確保每個表中的所有列的值都是原子的(不可再分的)。 3. 第二范式 (2NF): - 基於第一范式,並移除對主鍵的部分依賴。 5. 第三范式 (3NF): - 基於第二范式,並移除對主鍵的間接依賴(轉移依賴)。 正規化範例 --- - 假設我們有一個未正規化的訂單表: | 訂單ID | 客戶名 | 產品名 | 數量 | 價格 | 客戶地址 | | ----- | ----- | ----- | ---- | ---- |---- | | 001 | 張三 | 蘋果 | 3 | 10 | 台北市| | 002 | 李四 | 香蕉 | 5 | 15 | 高雄市 | | 003 | 張三 | 梨 | 2 | 8 | 台北市 | - 進行正規化後: 客戶表 (客戶ID, 客戶名, 客戶地址) | 客戶ID | 客戶名 | 客戶地址 | | ----- | ----- | ----- | | C01 | 張三 | 台北市 | | C02 | 李四 | 高雄市 | 產品表 (產品ID, 產品名, 價格) | 產品ID | 產品名 | 價格 | | ----- | ----- | ----- | | P01 | 蘋果 | 10 | | P02 | 香蕉 | 15 | | P03 | 梨 | 8 | 訂單表 (訂單ID, 客戶ID, 產品ID, 數量) | 訂單ID | 客戶ID | 產品ID | 數量 | | ----- | ----- | ----- | ----- | | 001 | C01 | P01 | 3 | | 002 | C02 | P02 | 5 | | 003 | C01 | P03 | 2 | 這樣的設計可以減少重複的數據(例如,"張三" 和 "台北市" 不需要在每個訂單中重複),並使數據庫結構更加清晰。 爲什麽有選擇性正規化/反正規化? --- 通常在實際開發中,數據庫的正規化程度通常取決於應用的具體需求。理想情況下,數據庫應該正規化到第三正規化(3NF),以確保數據完整性和減少多餘數據。 然而,有時過度正規化可能導致以下問題,這就是為什麼開發中不一定要到第三正規化的一些原因: 1. 性能問題: - 過度正規化可能導致需要多次連接(JOIN)操作以重新組合數據,這可能會對性能造成負面影響,尤其是在大型數據庫和高流量的應用中。 2. 複雜的查詢: - 更多的表意味著查詢將變得更加複雜,這可能會增加錯誤發生的機率,並使維護變得更困難。 3. 平衡讀寫操作: - 在某些應用中,可能需要平衡讀寫操作的效率。過度正規化可能提高寫操作的效率(因為更新操作更簡單),但讀操作可能因多次連接操作而變慢。 4. 實際需求: - 有時候對數據進行適度正規化(如第二正規化2NF)就足夠了。例如,如果一個應用僅需要非常特定的查詢方式,且數據更新頻率不高,那麼過度正規化可能是不必要的。 5. 可讀性和維護: - 過度正規化可能會使數據庫結構變得非常複雜,這可能會降低代碼的可讀性和維護性。 例子:學生和課程的數據庫 --- 假設我們有一個學生和課程的數據庫,學生可以選修多門課程。 ### 1. 未正規化的數據表: | 學生ID | 學生名稱 | 課程 | 課程教師 | | ----- | ----- | ----- | ---- | | 001 | 張三 | 數學 | 李老師 | | 001 | 張三 | 英語 | 王老師 | | 002 | 李四 | 數學 | 李老師 | | 003 | 王五 | 物理 | 趙老師 | 在這個未正規化的數據表中,「張三」的名稱被重複記錄了多次。如果需要更新「張三」的名字,就需要在多個地方進行修改,這增加了維護成本並有可能導致數據不一致。 ### 2. 第一正規化(1NF): 將數據表拆分為兩個表,一個是學生信息表,另一個是課程選修表。 **學生表:** | 學生ID | 學生名稱 | | ----- | ----- | | 001 | 張三 | | 002 | 李四 | | 003 | 王五 | **課程選修表:** | 學生ID | 課程 | 課程教師 | | ----- | ----- | ----- | | 001 | 數學 | 李老師 | | 001 | 英語 | 王老師 | | 002 | 數學 | 李老師 | | 003 | 物理 | 趙老師 | 這樣,學生的名字只需要在學生表中更新一次,其他關聯的就不要改名字了。 ### 3. 第二正規化(2NF): 進一步拆分課程選修表,將「課程」和「教師」拆分出來。 **課程表:** | 課程 | 課程教師 | | ----- | ----- | | 數學 | 李老師 | | 英語 | 王老師 | | 物理 | 趙老師 | **學生選課表:** | 學生ID | 課程 | | ----- | ----- | | 001 | 數學 | | 001 | 英語 | | 002 | 數學 | | 003 | 物理 | 這樣,如果需要更改某門課程的教師,只需要在課程表中進行修改。 ### 4. 第三正規化(3NF): 如果教師信息還包括其他屬性(如辦公室位置等),可以進一步拆分。 **教師表:** | 教師名 | 辦公室位置 | | ----- | ----- | | 李老師 | A棟101 | | 王老師 | B棟202 | | 趙老師 | C棟303 | **課程表:** | 課程 | 教師名 | | ----- | ----- | | 數學 | 李老師 | | 英語 | 王老師 | | 物理 | 趙老師 | 這樣,如果需要更新教師的辦公室位置,只需要在教師表中進行修改。 ### 5. 例子總結: 在該例子中可以看到正規化是如何減少冗餘數據,提高數據一致性,並使更新操作更簡單。 然而,這也增加了查詢的複雜性,因為現在需要多表連接來重建原始信息。這就是為什麼在某些情況下,可能會選擇進行部分正規化或甚至反正規化的原因。 總結 --- 在開發過程中正規化是數據庫設計中的一個重要過程,也很常見,它可以提高數據一致性和完整性,提升查詢效率,並使數據庫更易於維護和擴展。通過有效的索引策略,正規化還有助於提高數據庫的整體性能和存儲效率。對於任何需要長期維護和擴展的數據庫應用,然而進行正規化其中還需要考量是否理想,太多 (jion) 也是會發生不必要的麻煩以及查詢性能影響。 參考資料: --- - [資料庫設計的基本概念](https://support.microsoft.com/zh-hk/topic/%E8%B3%87%E6%96%99%E5%BA%AB%E8%A8%AD%E8%A8%88%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5-eb2159cf-1e30-401a-8084-bd4f9c9ca1f5)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up