{
  "slug": "materialized-view",
  "term": "Materialized view",
  "aliases": [
    "materialised view"
  ],
  "definition": "A materialized view stores the result of a query for later reads instead of recomputing that result for each read.",
  "note": "Stored result: PostgreSQL 18 retains both the query and its materialized rows. Reads use those rows, which may lag the underlying sources; this differs from an ordinary view evaluated on access. [pg-views]\n\nRefresh: In PostgreSQL 18, REFRESH MATERIALIZED VIEW with data replaces the stored result by running its defining query. WITH NO DATA instead leaves the view unscannable. CONCURRENTLY requires an already populated view and a UNIQUE index over plain columns that covers every row, without an expression index or WHERE predicate. It cannot be combined with WITH NO DATA. These are PostgreSQL rules, not promises for every engine. [pg-refresh]\n\nRecovery: A stored result is not automatically an independent recovery copy. If it must be rebuilt, identify the surviving source state and verify the reconstructed output against the required endpoint. If that rebuild blocks accepted service, include it in recovery timing. These are Hesela engineering inferences from source-dependent recovery planning. [recovery-derived]",
  "status": "shipping",
  "advantages": [],
  "limitations": [
    {
      "text": "PostgreSQL 18 pg_dump -t selects a materialized-view definition, not its cached rows, and does not automatically include its dependencies. In ordinary PostgreSQL 18.0 logical dumps, when included, the data item for a populated materialized view is a REFRESH command. This does not describe physical backups or binary-upgrade mode.",
      "citationIds": [
        "pg-dump",
        "pg-dump-matview-source"
      ]
    },
    {
      "text": "Preserving base tables and a query is not always enough to reproduce an older result. The documented sales-summary query uses CURRENT_DATE, which depends on transaction start. A later refresh can therefore change the selection even with unchanged base rows.",
      "citationIds": [
        "pg-views",
        "pg-current-date"
      ]
    }
  ],
  "related": [
    "recovery-point-objective",
    "recovery-time-objective"
  ],
  "supersedes": [],
  "supersededBy": [],
  "firstSeen": null,
  "lastSeen": null,
  "updated": "2026-11-01",
  "citations": [
    {
      "id": "pg-views",
      "title": "PostgreSQL 18: Materialized Views, section 39.3",
      "url": "https://www.postgresql.org/docs/18/rules-materializedviews.html",
      "accessed": "2026-11-01"
    },
    {
      "id": "pg-refresh",
      "title": "PostgreSQL 18: REFRESH MATERIALIZED VIEW, population and concurrent-refresh requirements",
      "url": "https://www.postgresql.org/docs/18/sql-refreshmaterializedview.html",
      "accessed": "2026-11-01"
    },
    {
      "id": "recovery-derived",
      "title": "AWS Well-Architected REL13-BP01: source-dependent reconstruction, implementation guidance question 4",
      "url": "https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_planning_for_recovery_objective_defined_recovery.html",
      "accessed": "2026-11-01"
    },
    {
      "id": "hesela-recovery",
      "title": "Hesela: Snapshots and backups: which failures can you recover from?",
      "url": "https://hesela.com/analyses/snapshot-backup-recovery-boundaries/",
      "accessed": "2026-11-01"
    },
    {
      "id": "pg-dump",
      "title": "PostgreSQL 18: pg_dump, -t selection and dependency limits",
      "url": "https://www.postgresql.org/docs/18/app-pgdump.html",
      "accessed": "2026-11-01"
    },
    {
      "id": "pg-dump-matview-source",
      "title": "PostgreSQL 18.0 pg_dump.c: refreshMatViewData and dumpTableSchema",
      "url": "https://github.com/postgres/postgres/blob/REL_18_0/src/bin/pg_dump/pg_dump.c",
      "accessed": "2026-11-01"
    },
    {
      "id": "pg-current-date",
      "title": "PostgreSQL 18: Date/Time Functions, section 9.9.5, transaction-relative current time",
      "url": "https://www.postgresql.org/docs/18/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT",
      "accessed": "2026-11-01"
    }
  ],
  "provenance": [
    "Refresh and population details describe PostgreSQL 18, not a universal SQL interface. Recovery recommendations are engineering inferences; no database recovery experiment or performance measurement was performed. [pg-views] [pg-refresh] [recovery-derived]",
    "Historical-result preservation and evaluation-time dependencies are engineering inferences from the documented query and pinned logical-dump implementation, not a restore experiment. [pg-views] [pg-current-date] [pg-dump-matview-source]"
  ]
}
