Appearance
Denormalization
Intentionally introducing redundancy into a normalized database to improve read performance.
Normalization → remove redundancy → more tables → more JOINs. Denormalization → add redundancy back → fewer tables → fewer JOINs.
When to Denormalize
- Read-heavy systems (90% reads, 10% writes)
- JOINs are killing performance (query runs 10,000 times/second with 5 table JOINs)
- Aggregations computed too often (
COUNT(*)on every profile view) - Data warehouses / analytics (OLAP)
Common Denormalization Techniques
1. Storing Derived/Computed Data
sql
-- Instead of: SELECT COUNT(*) FROM likes WHERE post_id = 101
-- Store: Posts table with like_count column
-- Increment like_count on every like2. Duplicating Columns Across Tables
sql
-- Normalized: Orders + Users → JOIN needed for user_name
-- Denormalized: Orders (order_id, user_id, user_name) → no JOIN3. Pre-joining Tables (Flattening)
sql
-- OrderSummary: user_id, user_name, order_id, product_name, qty, price
-- Single table scan instead of 4-way JOIN4. Storing Aggregates
sql
-- Users: (user_id, name, total_spent)
-- Update total_spent on every order → instant dashboard loadsWhen NOT to Denormalize
- Write-heavy tables — every write must update redundant data
- Frequently changing data — update one thing, must update many tables
- Small tables / simple queries — JOINs are already fast
- Strong consistency requirements (banking, financial)
Normalization vs Denormalization
| Normalized | Denormalized | |
|---|---|---|
| Redundancy | None | Intentional |
| Write speed | Faster | Slower |
| Read speed | Slower (joins) | Faster (no joins) |
| Consistency | Easy | Harder |
| Use case | OLTP, writes | OLAP, reads |
| Examples | Banking, ERP | Analytics, feeds |
Rule: Never denormalize first. Always normalize then denormalize where needed based on measured performance.