Create and refresh a materialized view
Oracle
-- FAST refresh first requires an MV log on the source table:
CREATE MATERIALIZED VIEW LOG ON sales
WITH ROWID, SEQUENCE (region, amount) INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW mv_revenue
BUILD IMMEDIATE REFRESH FAST ON COMMIT
AS SELECT region, SUM(amount) total, COUNT(*) cnt, COUNT(amount) amount_cnt
FROM sales GROUP BY region;
-- Manual refresh
EXEC DBMS_MVIEW.REFRESH('MV_REVENUE', 'C');REFRESH FAST requires a materialized view log; COMPLETE ('C') recomputes fully, FAST ('F') is incremental. ON COMMIT/ON DEMAND determines when the refresh happens.
PostgreSQL
CREATE MATERIALIZED VIEW mv_revenue AS
SELECT region, SUM(amount) AS total FROM sales GROUP BY region;
-- Refresh (CONCURRENTLY requires a unique index)
CREATE UNIQUE INDEX ON mv_revenue (region);
REFRESH MATERIALIZED VIEW CONCURRENTLY mv_revenue;REFRESH recomputes everything (it is not incremental). CONCURRENTLY does not block reads but requires a unique index and is slower.
MySQL
-- MySQL/MariaDB has no built-in materialized views.
-- Approach: summary table + refresh with a trigger or a scheduled event
CREATE TABLE mv_revenue (region VARCHAR(50) PRIMARY KEY, total DECIMAL(18,2));
CREATE EVENT ev_mv_revenue ON SCHEDULE EVERY 1 HOUR DO
REPLACE INTO mv_revenue SELECT region, SUM(amount) FROM sales GROUP BY region;There is no native materialized view support. A summary table is maintained and repopulated either instantly with triggers or periodically with the EVENT SCHEDULER.
SQL Server
-- Indexed view (materialized view equivalent)
CREATE VIEW dbo.mv_revenue WITH SCHEMABINDING AS
SELECT region, SUM(ISNULL(amount, 0)) AS total, COUNT_BIG(*) AS cnt
FROM dbo.sales GROUP BY region;
GO
CREATE UNIQUE CLUSTERED INDEX ix_mv_revenue ON dbo.mv_revenue (region);SQL Server uses indexed views: WITH SCHEMABINDING is mandatory; once a unique clustered index is created, the data is physically stored and maintained automatically (no separate REFRESH needed). With GROUP BY, COUNT_BIG(*) is required; if the column inside SUM is nullable, write SUM(ISNULL(amount, 0)) (otherwise error 8662). The view must be created with QUOTED_IDENTIFIER and ANSI_NULLS ON. Automatic view matching by the query optimizer is available only in Enterprise (and Developer) edition; in Standard, reference the view with the WITH (NOEXPAND) hint.
MongoDB
// On-demand materialized view: write the result to a collection with $merge
db.sales.aggregate([
{ $group: { _id: "$region", total: { $sum: "$amount" } } },
{ $merge: { into: "mv_revenue", whenMatched: "replace", whenNotMatched: "insert" } }
]);An on-demand materialized view is obtained by writing the aggregation result to a persistent collection with $out or $merge. To refresh, rerun the pipeline (manually or with a scheduler).
Redis
# Not applicable: Redis has no materialized views. The computed result is written to a key
# and cached with a TTL.
SET mv:revenue:region1 12345 EX 3600There is no materialized view concept; the closest approach is to keep precomputed values in keys (String/Hash/Sorted Set) and cache them for a limited time with EX/TTL.
Elasticsearch
# Continuous/materialized summary index with a transform
PUT _transform/mv_revenue
{ "source": { "index": "sales" },
"dest": { "index": "mv_revenue" },
"pivot": { "group_by": { "region": { "terms": { "field": "region" } } },
"aggregations": { "total": { "sum": { "field": "amount" } } } } }
POST _transform/mv_revenue/_startA transform pivots the source index and materializes it into a summary destination index. This example is a batch transform: it runs once with _start and stops. For a continuous transform that updates automatically as new data arrives, add "sync": { "time": { "field": "<time_field>", "delay": "60s" } } with a time field to the configuration (there is no continuous: true setting).