Each fact lives in one place
Normalization is the practice of splitting your data across tables so that each fact is stored exactly once. The opposite — denormalized data — duplicates facts across rows, which means every update has to find and change every copy.
Compare two designs for blog posts and authors:
- Denormalized: a
poststable with columnsauthor_name,author_email,author_bio. If Alice writes 100 posts, her name/email/bio is stored 100 times. Update her email — touch 100 rows. Forget one — corrupted state. - Normalized: a
poststable withauthor_id(foreign key) and a separateauthorstable with one row per author. Update Alice's email — one row.
The cost of normalization is joins (next lessons). The cost of denormalization is update anomalies and storage waste. For most application data, normalize first; denormalize selectively when you measure a real read-side bottleneck.
Principle: Normalize for writes; denormalize for reads — but only after you've measured. Premature denormalization in a SQLite app usually costs more in update bugs than it ever saves in query speed.