All Products
Search
Document Center

PolarDB:Real-time materialized views

Last Updated:Jul 16, 2026

Standard materialized views improve query performance by storing precomputed results, but their data goes stale the moment a base table changes. Refreshing them requires a full scan, making frequent refresh impractical for high-read workloads.

Real-time materialized views solve this by maintaining view data incrementally — after each DML statement on a base table, only the affected rows are recalculated and applied. Queries always return current data without the cost of a full refresh.

Supported versions

PostgreSQL version Minimum minor engine version
PostgreSQL 14 2.0.14.8.11.0
PostgreSQL 11 2.0.11.9.27.0

To check your current version, run SHOW polardb_version; or view the minor engine version in the console. If your version doesn't meet the requirement, upgrade the minor engine version.

How it works

Create

When you create a real-time materialized view:

  1. The system rewrites the view query to compute hidden columns required for maintenance.

  2. A trigger is created on the base table to capture changes.

  3. Where conditions are met, unique indexes are created on the view to accelerate incremental refreshes.

Incremental refresh

When data in the base table changes:

  1. The DML statement fires the trigger on the base table.

  2. The trigger retrieves the incremental data (the delta).

  3. The delta is calculated based on the view definition and the incremental data.

  4. The delta is applied to the view, completing the incremental refresh.

Refresh happens automatically after each statement commits. No manual refresh is needed for views created with WITH DATA.

Drop

Dropping a real-time materialized view removes both the incremental refresh trigger from the base table and the view itself.

Glossary

Term Definition
Base tables Standard tables referenced in the materialized view definition
Delta A collection of incremental changes (additions or deletions) that occur in a base table
Refresh A maintenance operation that updates the materialized view to match current data in its base tables
Apply delta The process of applying the calculated delta to a real-time materialized view

Performance considerations

Real-time materialized views improve read performance but add overhead to base table writes. Each DML statement fires a trigger and computes an incremental refresh, so write-heavy workloads pay a higher per-operation cost.

Use real-time materialized views when:

  • Read operations significantly outweigh writes

  • Query performance on large datasets matters more than write throughput

Avoid real-time materialized views when:

  • Writes are frequent or involve large volumes of data

  • Write latency is a hard requirement

The actual overhead depends on the view definition, write payload size, base table structure, and indexes. Test in a staging environment before deploying to production.

Reducing ongoing maintenance overhead

  • Limit the number of views per table. Each additional real-time materialized view on a base table adds a separate trigger and refresh cycle.

  • Use batch writes. Prefer COPY or INSERT INTO SELECT over row-by-row inserts to reduce trigger firing frequency.

  • Include the primary key in projections. Each base table must have a primary key, and that key must appear in the view projection columns to enable efficient delta lookups.

Limits

View definition limits

Category Supported Not supported
Base table type Standard tables Partitioned tables, inherited tables
Functions IMMUTABLE functions Mutable functions
Query constructs Simple queries, projections, DISTINCT, aggregate functions Subqueries, [NOT] EXISTS, [NOT] IN, LIMIT, HAVING, DISTINCT ON, WITH (CTE), ORDER BY, window functions, GROUPING SETS, CUBE, ROLLUP, UNION, INTERSECT, EXCEPT
Aggregate functions MIN, MAX, SUM, AVG, COUNT Other aggregate functions
Joins INNER JOIN, OUTER JOIN

Limits on GROUP BY

All columns in a GROUP BY clause must also appear in the projection.

Limits on OUTER JOIN

OUTER JOIN (including LEFT JOIN, RIGHT JOIN, and FULL JOIN) requires minor engine version 2.0.14.18.37.0 or later.

Additional restrictions apply:

  • OUTER JOIN cannot be combined with DISTINCT.

  • OUTER JOIN cannot be combined with GROUP BY.

  • OUTER JOIN cannot be combined with aggregate functions.

  • The FROM clause cannot mix OUTER JOIN with a comma-separated table list.

  • Only simple equi-join conditions are supported. Conditions using AND/OR operators, or equi-joins where both sides reference columns from the same table, are not supported.

  • All columns used in the JOIN condition must appear in the projection.

DDL restrictions on base tables

After you create a real-time materialized view on a base table:

  • DROP TABLE requires the CASCADE option.

  • ALTER TABLE cannot remove or modify columns referenced by the view.

Usage

Step 1: Install the extension

In the database where you want to use real-time materialized views, install the polar_ivm extension:

CREATE EXTENSION polar_ivm WITH SCHEMA pg_catalog;

Run this once per database.

Step 2: Create a real-time materialized view

CREATE MATERIALIZED VIEW table_name [ (column_name [, ...] ) ]
REFRESH FAST
ON COMMIT
AS query
[ WITH [ NO ] DATA ]

Parameters

Parameter Description
table_name Name of the view to create. Can be schema-qualified.
column_name Column name in the new view. If omitted, names are taken from the query output column names.
WITH DATA Default. Populates the view immediately on creation and enables real-time refresh.
WITH NO DATA Creates the view structure only, with no data. The view is not updated in real time until you run REFRESH MATERIALIZED VIEW. Queries return an error until then.
query The view definition: a SELECT, TABLE, or VALUES command. Runs in a security-restricted context.

Step 3: (Optional) Populate a view created with WITH NO DATA

If you created the view with WITH NO DATA, run the following command to populate it and enable real-time refresh:

REFRESH MATERIALIZED VIEW table_name

Where table_name is the name of the view (can be schema-qualified).

For views created with WITH DATA, data consistency is maintained automatically. Manual refresh calls on these views are skipped.

Drop a real-time materialized view

DROP MATERIALIZED VIEW [ IF EXISTS ] table_name [, ...] [ CASCADE | RESTRICT ]
Parameter Description
IF EXISTS Suppresses the error if the view does not exist. A notice is issued instead.
table_name Name of the view to drop. Can be schema-qualified.
CASCADE Drops dependent objects (such as other views) automatically.
RESTRICT Refuses to drop the view if any objects depend on it. This is the default.

Examples

Real-time materialized view with aggregate functions

  1. Install the polar_ivm extension.

    CREATE EXTENSION IF NOT EXISTS polar_ivm WITH SCHEMA pg_catalog;
  2. Create a base table and insert initial data.

    CREATE TABLE t (a INT, b VARCHAR);
    INSERT INTO t VALUES
      (1, 'a'),
      (2, 'b'),
      (3, 'c'),
      (4, 'd'),
      (5, 'e');
  3. Create a real-time materialized view using MAX, MIN, and GROUP BY.

    CREATE MATERIALIZED VIEW mv
    REFRESH FAST
    ON COMMIT
    AS
    SELECT max(a), min(a), b FROM t GROUP BY b;
  4. Query the view and verify it reflects the base table.

    SELECT * FROM mv ORDER BY b;

    Result:

     max | min | b
    -----+-----+---
       1 |   1 | a
       2 |   2 | b
       3 |   3 | c
       4 |   4 | d
       5 |   5 | e
    (5 rows)
  5. Insert a row and verify the view updates automatically.

    INSERT INTO t VALUES (6, 'f');
    SELECT * FROM mv ORDER BY b;

    Result:

     max | min | b
    -----+-----+---
       1 |   1 | a
       2 |   2 | b
       3 |   3 | c
       4 |   4 | d
       5 |   5 | e
       6 |   6 | f
    (6 rows)
  6. Delete a row and verify the view updates automatically.

    DELETE FROM t WHERE a = 2;
    SELECT * FROM mv ORDER BY b;

    Result:

     max | min | b
    -----+-----+---
       1 |   1 | a
       3 |   3 | c
       4 |   4 | d
       5 |   5 | e
       6 |   6 | f
    (5 rows)
  7. Update rows and verify the view updates automatically.

    UPDATE t SET a = a + 1;
    SELECT * FROM mv ORDER BY b;

    Result:

     max | min | b
    -----+-----+---
       2 |   2 | a
       4 |   4 | c
       5 |   5 | d
       6 |   6 | e
       7 |   7 | f
    (5 rows)
  8. Drop the view when done.

    DROP MATERIALIZED VIEW mv;

Real-time materialized view with an OUTER JOIN

OUTER JOIN support requires minor engine version 2.0.14.18.37.0 or later.
  1. Install the polar_ivm extension.

    CREATE EXTENSION IF NOT EXISTS polar_ivm WITH SCHEMA pg_catalog;
  2. Create two base tables and insert initial data.

    CREATE TABLE t1 (a INT, b VARCHAR);
    INSERT INTO t1 VALUES
      (1, 'a'),
      (2, 'b'),
      (3, 'c'),
      (4, 'd'),
      (5, 'e');
    
    CREATE TABLE t2 (a INT, c VARCHAR);
    INSERT INTO t2 VALUES
      (1, 'e'),
      (2, 'f');
  3. Create a real-time materialized view using a LEFT JOIN. All join-condition columns (t1.a, t2.a) are included in the projection, as required.

    CREATE MATERIALIZED VIEW mv
    REFRESH FAST
    ON COMMIT AS
    SELECT t1.a AS t1a, t1.b,
           t2.a AS t2a, t2.c
    FROM t1 LEFT JOIN t2
    ON t1.a = t2.a;
  4. Query the view and verify it reflects the base tables.

    SELECT * FROM mv ORDER BY b;

    Result:

     t1a | b | t2a | c
    -----+---+-----+---
       1 | a |   1 | e
       2 | b |   2 | f
       3 | c |     |
       4 | d |     |
       5 | e |     |
  5. Insert a row into t2 and verify the view updates automatically.

    INSERT INTO t2 VALUES (3, 'g');
    SELECT * FROM mv ORDER BY b;

    Result:

     t1a | b | t2a | c
    -----+---+-----+---
       1 | a |   1 | e
       2 | b |   2 | f
       3 | c |   3 | g
       4 | d |     |
       5 | e |     |
  6. Delete rows from t1 and verify the view updates automatically.

    DELETE FROM t1 WHERE a IN (1, 4);
    SELECT * FROM mv ORDER BY b;

    Result:

     t1a | b | t2a | c
    -----+---+-----+---
       2 | b |   2 | f
       3 | c |   3 | g
       5 | e |     |
  7. Update rows in t2 and verify the view updates automatically.

    UPDATE t2 SET a = a + 1;
    SELECT * FROM mv ORDER BY b;

    Result:

     t1a | b | t2a | c
    -----+---+-----+---
       2 | b |   2 | e
       3 | c |   3 | f
       5 | e |     |
  8. Drop the view when done.

    DROP MATERIALIZED VIEW mv;