일반 뷰는 쿼리문만 저장하므로 조회할 때마다 원본을 다시 읽는다. Materialized View 는 정의 쿼리의 결과를 저장 테이블에 물리적으로 담아 두고, 조회 시 그 테이블을 읽는다. 반복되는 무거운 집계에서 응답이 빨라지는 대신 저장 공간을 쓰고 최신성이 떨어진다.
| 항목 | View | Materialized View |
|---|---|---|
| 저장 내용 | 쿼리문 | 쿼리 결과 |
| 최신성 | 항상 최신 | 마지막 갱신 시점 |
| 저장 공간 | 없음 | 저장 테이블만큼 |
| 갱신 | 필요 없음 | REFRESH MATERIALIZED VIEW |
Materialized View 는 커넥터가 구현해야 쓸 수 있다. 저장 테이블을 만들어야 하므로 쓰기가 되는 레이크하우스 계열 커넥터에서만 제공된다. Iceberg · Delta Lake · Hive 처럼 테이블을 만들 수 있는 커넥터가 대상이고, PostgreSQL · Oracle · MySQL 같은 RDBMS 커넥터에서는 만들 수 없다. 원본 데이터가 RDBMS 에 있더라도 Materialized View 자체는 Iceberg 같은 카탈로그에 만들고 정의 쿼리에서 RDBMS 를 읽는 형태가 된다.
지원 여부는 버전과 커넥터마다 다르므로 실제로 쓰기 전에 해당 커넥터 문서의 SQL 지원 절을 확인한다.
CREATE MATERIALIZED VIEW iceberg.sales.sales_summary AS
SELECT region, sum(amount) AS total_amount, count(*) AS order_count
FROM iceberg.sales.orders
GROUP BY region;
생성 직후에는 데이터가 없다. REFRESH 를 한 번 돌려야 저장 테이블이 채워진다.
REFRESH MATERIALIZED VIEW iceberg.sales.sales_summary;
자동 갱신은 없다. Airflow·cron 같은 외부 스케줄러로 주기를 만든다. 정의와 상태는 이렇게 본다.
SHOW CREATE MATERIALIZED VIEW iceberg.sales.sales_summary;
SELECT * FROM system.metadata.materialized_views;
Trino 는 Materialized View 를 읽을 때 저장된 데이터가 아직 유효한지 판단한다. 유효하면 저장 테이블을 읽고, 원본이 바뀌어 낡았다고 판단되면 정의 쿼리를 그 자리에서 실행해 정확한 결과를 돌려준다. 따라서 갱신을 잊어도 틀린 값이 나오지는 않지만, 성능 이점이 사라진다.
CREATE MATERIALIZED VIEW 의 GRACE PERIOD 절로 "얼마 동안은 낡아도 저장된 결과를 그대로 쓴다" 를 정할 수 있다. REFRESH 를 할 때마다 이 기간이 다시 시작된다. WHEN STALE 관련 동작은 커넥터가 지원해야 한다.
Trino 는 일반 테이블을 향한 쿼리를 옵티마이저가 알아서 Materialized View 로 바꿔 주지 않는다. 즉 상용 DBMS 의 query rewrite 와는 다르다. 이득을 보려면 쿼리에서 Materialized View 를 직접 가리켜야 한다.
INSERT · UPDATE · DELETE 로 Materialized View 를 직접 고칠 수 없다. 내용은 정의 쿼리와 REFRESH 로만 바뀐다. 원본 테이블의 컬럼이 바뀌면 정의 쿼리가 깨져 조회와 갱신이 모두 실패하므로, 스키마를 바꿀 때는 의존하는 Materialized View 를 함께 본다. 만들 때는 정의 쿼리가 읽는 모든 테이블에 대한 SELECT 권한이 필요하다.
DROP MATERIALIZED VIEW iceberg.sales.sales_summary;
Impala 의 Materialized View 지원 · Trino 커넥터