jongkwan.dev
Development · Essay №012

Database Denormalization Strategies

Denormalization techniques that deliberately break normalization to raise read performance, and the strategies for managing data integrity

Jongkwan Lee2025년 6월 7일4 min read
Contents

A design trade-off: deliberately break normalization to raise read performance, and take on the burden of managing data integrity in return.

What denormalization is

Denormalization is a design technique that intentionally breaks normalization and permits duplicate data in order to improve read performance.

Normalization minimizes data duplication and update anomalies, but when business requirements call for trading integrity guarantees for performance, denormalization is applied.

Why denormalize

Performance

sql
-- normalized structure: requires a 3-table JOIN
SELECT o.order_id, c.name, p.product_name
FROM orders o
JOIN customers c ON o.customer_id = c.id
JOIN products p ON o.product_id = p.id;
 
-- after denormalization: a single-table query
SELECT order_id, customer_name, product_name
FROM orders_denormalized;

Simpler development

Collapsing complex multi-way joins keeps both SQL and application logic concise.

Optimizing OLAP and BI environments

Online analytical processing (OLAP) and business intelligence (BI) tools scan large volumes of data repeatedly.

Removing the cost of repeatedly joining several tables in an analytics tool shortens analysis time.

The downsides

DownsideDescription
Data inconsistencyRisk of divergence when duplicated data is updated
Higher write costINSERT/UPDATE/DELETE touch more tables
Structural complexityHard to track where duplication is maintained
Maintenance burdenThe design intent becomes hard to recover over time

Denormalization techniques

Adding duplicate attributes

sql
-- store the customer name redundantly on the orders table
ALTER TABLE orders ADD COLUMN customer_name VARCHAR(100);
 
-- upside: query directly with no JOIN
-- downside: changing a customer name also requires updating orders

Storing aggregate results

sql
-- daily sales aggregate table
CREATE TABLE daily_sales_summary (
    date DATE PRIMARY KEY,
    total_sales DECIMAL(15, 2),
    order_count INT,
    avg_order_value DECIMAL(10, 2)
);
 
-- query precomputed results instead of aggregating in real time

Materialized views

sql
-- PostgreSQL
CREATE MATERIALIZED VIEW order_summary AS
SELECT
    date_trunc('day', order_date) as day,
    SUM(amount) as total,
    COUNT(*) as count
FROM orders
GROUP BY 1;
 
-- periodic refresh
REFRESH MATERIALIZED VIEW order_summary;

A MATERIALIZED VIEW stores aggregate results on disk like a real table. Changes to the underlying orders table are not reflected automatically, so REFRESH must run periodically to recompute the current state.

Replicating tables

Replicating frequently used reference data across several databases or shards cuts remote lookups, which reduces network traffic and latency together. Each replica needs its own synchronization path, so this suits data that changes infrequently.

Stepping down a normal form

Deliberately dropping from Boyce-Codd normal form (BCNF) to third normal form (3NF) puts more attributes in one table and reduces the number of joins. Update anomalies become possible in exchange, so apply this only to attributes that rarely change.

What to consider before applying it

Analyze the access pattern

  • Read-heavy (99% reads, 1% writes): denormalization is a good fit
  • Write-heavy (50% reads, 50% writes): evaluate denormalization carefully

Set explicit performance targets

  • Quantify the target query response time
  • Run adequate benchmark tests
  • Avoid denormalizing unconditionally

Choose a data synchronization strategy

ApproachUpsideDownside
TriggersReal-time synchronizationHigher database load
Batch jobsSpreads database loadTemporary inconsistency
Application logicFlexibleMore complex code

Check these first

Things to try before deciding to denormalize:

  1. Analyze the execution plan (EXPLAIN)
  2. Optimize indexes
  3. Introduce caching (Redis, Memcached)
  4. Tune the queries

Consider denormalization only when these are not enough.

Summary

EnvironmentRecommendation
OLAP, BI, data martsHigh
Read-heavy web servicesMedium
OLTP (online transaction processing)Low

Denormalization pays off where read performance is the bottleneck, but you must first decide who absorbs the cost of synchronizing duplicated data, and when. Choose the synchronization path among triggers, batch jobs, and application logic, and measure how long inconsistency is tolerable before adopting it.

Applying it without measuring the read ratio and the synchronization cost only makes the write path heavier. Set the criteria for reverting to indexes and caching in advance, for the case where the synchronization burden outgrows the benefit.