Hard postgresql sql

When is a materialized view useful, and how do you manage staleness?

The 30 second answer

A materialized view stores a query result so expensive reads can reuse it instead of recalculating everything. The tradeoff is freshness and refresh cost. I would use it for data that tolerates a defined delay, such as reporting, and make that delay visible. Before choosing it, I check whether a better query or index would solve the problem with less operational complexity.

In PostgreSQL, a materialized view stores the result of its defining query. Reads use that stored result rather than recomputing the original joins and aggregation every time. Unlike an ordinary view, it can have its own indexes. The benefit is cheaper repeated reads; the cost is storage, refresh work and stale data between refreshes.

For example, a customer-spend dashboard could read a precomputed daily summary. A payment-approval decision usually needs authoritative transactional state instead. I would define a freshness objective and expose when the summary was last successfully refreshed. A failed refresh must not silently turn a short accepted delay into indefinitely stale reporting.

REFRESH MATERIALIZED VIEW replaces the contents by running the defining query. Ordinary refresh can block readers. CONCURRENTLY avoids locking out concurrent selects, but requires an already populated view and at least one qualifying UNIQUE index: column names only, covering all rows, not an expression or partial index. Only one refresh can run against a given materialized view at a time. Concurrent refresh is not incremental maintenance and is not automatically cheaper.

My choice would compare a better source query/index with the refresh duration, database load and freshness budget. Schedule refreshes deliberately, record completion rather than just schedule time, and alert on age and failures. Query with an explicit ORDER BY when output ordering matters: refresh does not promise to preserve the defining query's order. These are PostgreSQL semantics; do not generalize every refresh option to another database.

Sources (2)
  1. PostgreSQL: Materialized Views
  2. PostgreSQL: REFRESH MATERIALIZED VIEW