Materialized Views Cheat Sheet
Materialized views across PostgreSQL, ClickHouse, and Snowflake covering creation syntax, refresh strategies, and indexing.
2 PagesIntermediateApr 2, 2026
PostgreSQL Materialized View
Create, index, and refresh a materialized view without blocking reads.
sql
CREATE MATERIALIZED VIEW daily_revenue ASSELECT date_trunc('day', created_at) AS day, sum(amount) AS revenue, count(*) AS order_countFROM ordersGROUP BY 1WITH DATA;-- Required for CONCURRENTLY refresh: a unique indexCREATE UNIQUE INDEX ON daily_revenue (day);-- Refresh without locking out concurrent readsREFRESH MATERIALIZED VIEW CONCURRENTLY daily_revenue;
ClickHouse & TimescaleDB Equivalents
Incrementally maintained materialized views, rather than full-refresh snapshots.
sql
-- ClickHouse: incrementally populated on every insert to the source tableCREATE MATERIALIZED VIEW daily_revenue_mvENGINE = SummingMergeTreeORDER BY day ASSELECT toDate(created_at) AS day, sum(amount) AS revenueFROM ordersGROUP BY day;-- TimescaleDB: continuous aggregate, refreshed on a scheduleCREATE MATERIALIZED VIEW daily_revenueWITH (timescaledb.continuous) ASSELECT time_bucket('1 day', created_at) AS day, sum(amount) AS revenueFROM ordersGROUP BY day;
Scheduling Refreshes (pg_cron)
Keep a Postgres materialized view fresh on a schedule.
sql
CREATE EXTENSION IF NOT EXISTS pg_cron;SELECT cron.schedule( 'refresh-daily-revenue', '*/15 * * * *', $$REFRESH MATERIALIZED VIEW CONCURRENTLY daily_revenue$$);-- Check scheduled jobsSELECT * FROM cron.job;
Materialized vs. Regular Views — Tradeoffs
When to reach for a materialized view instead of a plain view or app-level cache.
- Regular view- just a stored query, always live, zero storage, but re-executes the full query every time
- Materialized view- stores results on disk; fast reads, but data is stale until refreshed
- REFRESH ... CONCURRENTLY- Postgres-only, avoids locking readers out during refresh, requires a unique index
- Incremental MVs (ClickHouse, Timescale)- update as new rows arrive instead of full recompute, ideal for append-only event data
- Staleness budget- decide upfront how stale is acceptable; drives your refresh interval/schedule
Pro Tip
In PostgreSQL, `REFRESH MATERIALIZED VIEW` without `CONCURRENTLY` takes an ACCESS EXCLUSIVE lock and blocks all reads for the duration — always create the required unique index up front and use CONCURRENTLY in production, even though it's slower per refresh.
Was this cheat sheet helpful?
Explore Topics
#MaterializedViews#MaterializedViewsCheatSheet#Database#Intermediate#PostgreSQLMaterializedView#ClickHouseTimescaleDBEquivalents#SchedulingRefreshesPgCron#Materialized#Databases#CheatSheet#SkillVeris
Advertisement
Sri Hayavadhana Info-Tech
Professional Web Designing Services
- Responsive Websites
- E-commerce Solutions
- SEO Friendly Design
- Fast & Secure
- Support & Maintenance