정지용
기술스택 목록
데이터베이스

Materialized View

프로젝트 1에서 사용했습니다. 각 프로젝트에서 어떤 역할로 썼는지 아래에 정리했습니다.

이 기술은 무엇인가요?

쿼리 결과를 물리적으로 저장해두고 필요할 때 갱신해서 재사용하는 저장 뷰

Materialized View는 일반 뷰(View)처럼 쿼리를 정의해두지만, 매번 쿼리를 재실행하는 대신 결과를 실제 테이블처럼 디스크에 저장해두는 데이터베이스 객체입니다. 복잡한 JOIN이나 집계 쿼리를 매 요청마다 계산하면 비용이 크기 때문에, 결과를 미리 계산해두고 필요한 시점에 갱신하는 방식으로 조회 성능을 크게 높이기 위해 고안되었습니다. 최신 데이터가 즉시 반영되는 대신, 갱신 주기만큼의 지연을 감수하는 트레이드오프를 가집니다.

이럴 때 사용합니다

  • 여러 테이블을 조인·집계하는 무거운 리포트/대시보드 쿼리를 반복 실행할 때
  • 데이터가 실시간일 필요는 없고 분 단위·시간 단위 지연이 허용될 때
  • 동일한 집계 결과를 여러 클라이언트가 자주 조회해 캐싱 효과가 필요할 때
  • 원본 테이블은 자주 바뀌지만 조회 쿼리 자체는 무겁고 자주 변하지 않을 때

핵심 개념

REFRESH
저장된 결과를 최신 쿼리 실행 결과로 다시 채우는 작업으로, 수동 실행이나 스케줄러를 통해 주기적으로 수행한다.
CONCURRENTLY
갱신 도중에도 기존 뷰에 대한 읽기 조회를 막지 않도록 하는 옵션으로, 보통 별도의 unique index가 있어야 사용 가능하다.
Staleness (데이터 신선도)
마지막 REFRESH 시점 이후 원본 테이블이 바뀌어도 뷰 내용은 그대로이므로, 조회 결과가 실제와 다를 수 있는 시차를 의미한다.
View vs Materialized View
일반 뷰는 쿼리 자체를 저장해 매번 실행하지만, Materialized View는 실행 결과를 저장해 재계산 없이 바로 읽는다.
Unique Index
CONCURRENTLY 갱신이나 부분 갱신 등 고급 기능을 쓰기 위해 뷰에 걸어두는 인덱스로, 행을 유일하게 식별하는 역할을 한다.

프로젝트별 집계 결과를 저장하는 Materialized View

trades 테이블을 집계해 project_summary에 저장해두고, 이후에는 REFRESH로 재계산해 최신 결과를 유지한다.

SQL
-- 프로젝트별 거래 합계를 저장하는 Materialized View 생성
CREATE MATERIALIZED VIEW project_summary AS
SELECT
  project_id,
  COUNT(*) AS trade_count,
  SUM(amount) AS total_amount
FROM trades
GROUP BY project_id;

-- CONCURRENTLY 갱신을 위해서는 unique index가 필요
CREATE UNIQUE INDEX ON project_summary (project_id);

-- 조회를 막지 않고 최신 데이터로 갱신
REFRESH MATERIALIZED VIEW CONCURRENTLY project_summary;

처음 쓸 때 흔한 함정

  • REFRESH를 하지 않으면 원본 데이터가 바뀌어도 뷰 내용은 그대로 남아있다는 점을 놓치기 쉽다
  • CONCURRENTLY 옵션은 unique index가 없으면 사용할 수 없다
  • 갱신 쿼리 자체가 무거우면 REFRESH 시점에 부하가 몰릴 수 있다

위 개요는 기술 학습을 돕기 위해 자동 생성된 일반 설명입니다. 정확한 사양과 최신 정보는 공식 문서를 확인하세요.

프로젝트별 활용 방식

위 개념이 실제 프로젝트에서 어떻게 쓰였는지 보여줍니다.

함께 사용한 기술

위 프로젝트들에서 같이 쓰인 다른 기술입니다.