구체화된 뷰(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에는 materialized view log가 필요하다. COMPLETE('C')는 전체 재계산, FAST('F')는 증분 갱신이다. ON COMMIT/ON DEMAND가 갱신 시점을 결정한다.
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는 전체를 재계산한다(증분 아님). CONCURRENTLY는 읽기를 블로킹하지 않지만 unique 인덱스가 필요하고 더 느리다.
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;materialized view를 기본 지원하지 않는다. 요약 테이블을 두고 트리거로 즉시 또는 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는 indexed view를 사용한다. WITH SCHEMABINDING이 필수이며, unique clustered 인덱스를 생성하면 데이터가 물리적으로 저장되고 자동 유지된다(별도 REFRESH 불필요). GROUP BY가 있으면 COUNT_BIG(*)가 필요하고, SUM 안의 컬럼이 nullable이면 SUM(ISNULL(amount, 0))으로 작성한다(그렇지 않으면 오류 8662). 뷰는 QUOTED_IDENTIFIER와 ANSI_NULLS ON 상태에서 생성해야 한다. 쿼리 옵티마이저의 자동 뷰 매칭은 Enterprise(및 Developer) 에디션에서만 가능하며, Standard에서는 WITH (NOEXPAND) 힌트로 뷰를 참조한다.
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" } }
]);$out 또는 $merge로 aggregation 결과를 영구 컬렉션에 기록하면 온디맨드 materialized view를 얻을 수 있다. 갱신하려면 파이프라인을 다시 실행한다(수동 또는 스케줄러).
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 3600materialized view 개념이 없다. 가장 가까운 방법은 미리 계산한 값을 키(String/Hash/Sorted Set)에 두고 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/_starttransform은 소스 인덱스를 피벗하여 요약 대상 인덱스로 구체화한다. 이 예시는 batch transform으로, _start로 한 번 실행되고 멈춘다. 새 데이터가 들어올 때 자동으로 갱신되는 continuous transform을 원하면 구성에 시간 필드와 함께 "sync": { "time": { "field": "<time_field>", "delay": "60s" } }를 추가한다(continuous: true 설정은 없다).