Materialized Views


What are Materialized Views?

Materialized views pre-compute and store query results. Unlike regular views, they persist data on disk, trading storage for query speed.

Creating Materialized Views




-- PostgreSQL: materialized view for daily sales


CREATE MATERIALIZED VIEW daily_sales_summary AS


SELECT


d.date,


p.category,


COUNT(*) as sale_count,


SUM(s.amount) as total_sales


FROM fact_sales s


JOIN dim_date d ON s.date_id = d.date_id


JOIN dim_product p ON s.product_id = p.product_id


GROUP BY d.date, p.category;




-- Add index for faster queries


CREATE INDEX idx_daily_sales_date ON daily_sales_summary(date);




-- Query is much faster than the original


SELECT * FROM daily_sales_summary


WHERE date >= '2026-01-01';





Refresh Strategies

Complete Refresh

Rebuilds the entire view:




REFRESH MATERIALIZED VIEW daily_sales_summary;





Simple but locks the view during refresh. Best for small datasets or low-frequency refreshes.

Concurrent Refresh

Creates a new version and swaps atomically. No lock but requires a unique index:




CREATE UNIQUE INDEX idx_daily_sales_pk ON daily_sales_summary(date, category);


REFRESH MATERIALIZED VIEW CONCURRENTLY daily_sales_summary;





Incremental Refresh

Only processes changed data. Not natively supported in PostgreSQL but available in specialized databases.

Use Cases

| Use Case | Refresh Frequency | Benefit | |----------|------------------|---------| | Dashboards | Hourly | Sub-second queries | | Aggregations | Daily | Avoid full table scans | | Pre-joined data | On-demand | Eliminate expensive joins | | Reporting | Nightly | Consistent snapshot |

Performance Considerations




-- Compare query performance


EXPLAIN ANALYZE


SELECT date, SUM(total_sales)


FROM daily_sales_summary


WHERE date >= '2026-01-01'


GROUP BY date;




-- vs the base query (much slower)


EXPLAIN ANALYZE


SELECT d.date, SUM(s.amount)


FROM fact_sales s


JOIN dim_date d ON s.date_id = d.date_id


WHERE d.date >= '2026-01-01'


GROUP BY d.date;





Conclusion

Materialized views are essential for dashboard and reporting performance. Use concurrent refresh to avoid locks. Add indexes on frequently filtered columns. Choose refresh strategy based on freshness requirements. Monitor storage overhead for large views.