Computer Science

[Database] Materialized View

0. Materialized View

Materialized View는 데이터베이스에서 쿼리의 결과를 미리 계산하여 저장하는 실제 테이블로, 데이터량이 많거나 복잡한 쿼리를 실행할 때 발생하는 성능 문제를 완화하기 위해 사용된다.

많은 양의 데이터를 처리해야 하는 경우, 복잡한 쿼리의 실행은 데이터베이스 서버에 부하를 줄 수 있고, 응답 시간이 길어질 수 있다. 특히, 필자의 경우에는 프로덕트에서 해당 API에 직접 요청을 주는데, 추후 트래픽이 증가하면 데이터베이스의 성능이 저하되어 서비스 중단이 발생할 위험이 있다고 판단했다.

materialized view 테이블에 대해서 몰랐던 나는, ETL 잡을 돌리면서 쿼리 결과를  DB테이블 생성해서 저장해두는 방법을 생각했었다. 그러나 매일 바뀌는 연산 결과를 매일 ETL잡을 돌리면서 테이블 Update 혹은 Delete -> Create 하는 방법이 우리 목적에는 부합하지 않다고 판단되었고, materialized view라는 걸 알게되었다. 

결론적으로, Materialized View를 사용하면 쿼리의 결과를 사전에 계산하여 테이블에 저장함으로써, 쿼리 실행 시 원본 데이터베이스에 매번 접근하지 않고 저장된 결과를 바로 조회할 수 있다. 실행 시간을 줄이고, 데이터베이스 서버의 부하를 감소시키는 장점이 있다. 

 

그렇다면, View와는 어떻게 다를까?


1. 데이터 저장 방식

  • view: 가상의 테이블로, 뷰를 정의하는 쿼리가 실행될 때마다 실시간으로 결과 생성. 원본 테이블에 저장된 데이터는 별도로 저장되지 않음
  • Materialized View: 실제로 데이터를 저장하는 테이블. 쿼리의 결과가 사전에 계산되어 테이블에 저장되므로, 데이터는 실시간으로 업데이트되지 않고 정적으로 유지됨.

2. 데이터 접근 속도

  • view: 쿼리 실행 시 원본 테이블에 접근하여 데이터를 조회 -> 조회 속도가 원본 테이블의 성능에 영향 받음
  • Materialized View: 데이터를 사전에 계산하여 테이블에 저장 -> 쿼리 실행 시 미리 계산된 결과를 바로 조회. 매우 빠른 데이터 접근 속도.

3. 업데이트 방식:

  • view: 일반적인 뷰는 원본 테이블에 직접 접근하기 때문에, 원본 테이블에 발생하는 변경사항이 즉시 반영.
  • Materialized View: 정적으로 데이터를 저장하기 때문에, 원본 테이블에 변경이 발생하면 해당 변경을 수동으로 반영해주어야 함.

View 테이블과는 이러한 차이점들이 있다. 필자의 경우는 프로덕트 테이블의 materialized view 테이블을 업데이트해줄 수 있는 ETL 잡이 실행될 수 있는 환경이 이미 구축되어 있기 때문에, 업데이트 방식에는 큰 단점을 느끼지 못하고 도입하게 되었다.

 

Materialized view를 지원하는 DBMS들

1. PostgreSQL: PostgreSQL은 Materialized View를 내장하고 있으며, 위에서 설명한 문법을 사용하여 Materialized View를 생성, 갱신, 삭제 가능

2. Oracle: `CREATE MATERIALIZED VIEW` 문을 사용하여 Materialized View를 생성하고, `REFRESH` 명령을 사용하여 업데이트.

3. Microsoft SQL Server: SQL Server 2016부터 Materialized View 기능 도입됨.

4. MySQL: MySQL은 일부 확장 기능 또는 서드파티 플러그인을 통해 Materialized View를 지원하지만 기본적으로 내장된 기능은 아님.

5. Apache Cassandra: Apache Cassandra는 Materialized View를 지원

등등이 있고, 필자의 경우에는 postgresql을 사용하고 있다.

 

쿼리 문법( Postgresql 쿼리 기준 )

1. 생성

CREATE MATERIALIZED VIEW [view_name] AS
SELECT [columns]
FROM [tables]
WHERE [conditions]
[GROUP BY [columns]]
[HAVING [conditions]]
[ORDER BY [columns]];

CREATE MATERIALIZED VIEW [view_name] AS 뒤에 materialzed view테이블로 저장하려는 쿼리를 작성하면 된다. 

 

2. 업데이트

REFRESH MATERIALIZED VIEW [view_name];

앞에서 소개한 대로, 정적인 테이블이기때문에 업데이트가 필요한 경우 직접 refresh 쿼리를 날려주어야한다. 필자의 경우, ETL잡에서 매일 refresh쿼리를 날려주도록 했다.

 

3. 삭제

DROP MATERIALIZED VIEW [view_name];

 


Materialized view 테이블에 쿼리결과를 미리 저장해놓으면서, 쿼리 조회 결과를 최대 87초까지 기다리던 페이지가 3초이내로 응답하게 되었다. 데이터량이 많고 복잡한 쿼리를 자주 실행해야 하는 상황에서는 Materialized View를 활용하여 성능을 최적화하는 방법을 고려해보자!