Database Normalization
Database normalization is the process of structuring a relational database in accordance with a series of so-called normal forms in order to reduce data redundancy and improve data integrity.
1. The Goals
- Eliminate Redundant Data: Storing the same data in more than one place wastes space and creates maintenance nightmares (Update Anomalies).
- Ensure Data Dependencies Make Sense: Data should be stored logically.
2. The Normal Forms
Normalization is progressive. To be in 2NF, you must first be in 1NF.
First Normal Form (1NF)
- Atomicity: Each column must contain atomic values (no lists or comma-separated strings).
- Uniqueness: Each row must be unique (Primary Key).
- Example Violation: Storing "Red, Blue" in a
Colorscolumn. - Fix: Create a separate row for "Red" and "Blue", or a separate table.
Second Normal Form (2NF)
- Prerequisite: Must be in 1NF.
- No Partial Dependencies: All non-key attributes must depend on the entire primary key. This applies mainly when the Primary Key is composite (made of multiple columns).
- Example Violation: Table
OrderItemshas PK(OrderId, ItemId)and columnsItemName,ItemPrice.ItemPricedepends only onItemId, notOrderId. - Fix: Move
ItemNameandItemPriceto a separateItemstable.
Third Normal Form (3NF)
- Prerequisite: Must be in 2NF.
- No Transitive Dependencies: Non-key attributes must not depend on other non-key attributes.
- Example Violation: Table
UsershasZipCodeandCity.Citydepends onZipCode. IfZipCodechanges,Citymust change. - Fix: Move
ZipCodeandCityto aLocationstable.
Boyce-Codd Normal Form (BCNF)
A slightly stronger version of 3NF. It handles rare cases where a non-key attribute determines a part of the primary key.
3. Denormalization
Normalization is great for data integrity (Write-Optimized), but it can hurt read performance because retrieving data requires joining many tables.
Denormalization is the process of intentionally adding redundancy to the database to speed up reads.
- Example: Storing
UserCounton aGrouptable instead of runningSELECT COUNT(*) FROM Users WHERE GroupID = ?every time. - Trade-off: You gain read speed but lose write speed (you have to update
UserCountevery time a user joins/leaves) and risk data inconsistency.
4. Summary
| Form | Rule | Mnemonic |
|---|---|---|
| 1NF | Atomic values | The Key |
| 2NF | No partial dependencies | The Whole Key |
| 3NF | No transitive dependencies | And Nothing But The Key |
"The data depends on the key, the whole key, and nothing but the key, so help me Codd."
programming/database-basics programming/database-indexing programming/database-sharding