2 min read

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

  1. Eliminate Redundant Data: Storing the same data in more than one place wastes space and creates maintenance nightmares (Update Anomalies).
  2. 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 Colors column.
  • 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 OrderItems has PK (OrderId, ItemId) and columns ItemName, ItemPrice. ItemPrice depends only on ItemId, not OrderId.
  • Fix: Move ItemName and ItemPrice to a separate Items table.

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 Users has ZipCode and City. City depends on ZipCode. If ZipCode changes, City must change.
  • Fix: Move ZipCode and City to a Locations table.

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 UserCount on a Group table instead of running SELECT COUNT(*) FROM Users WHERE GroupID = ? every time.
  • Trade-off: You gain read speed but lose write speed (you have to update UserCount every 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