5.3Optimizing Queries with Materialized Views
자주 사용되고 비싼 쿼리지만 업데이트 주기가 길 때 쓰는 Materialized View
Materialized View
지난번 포스팅에서 살펴본 VIEW
는, 참조될 시 실행되는 쿼리다.
이번에 살펴볼 Materialized View
는 특정 시점에서만 실행되는 쿼리로, 해당 쿼리 결과는 저장되어 다시 쿼리를 실행하지 않아도 참조될 수 있다.
Creating Materialized View
매 주별 posts와 comments가 받은 좋아요 숫자를 표시하는 쿼리를 작성해보자.
테이블은 posts
(id, created_at), likes
(post_id, comment_id), comments
(id, created_at)가 있다.
우선 데이터 전체를 선택한 후, 필요한 것만으로 좁혀보자.
sqlSELECT * FROM likes LEFT JOIN posts ON posts.id = likes.post_id LEFT JOIN comments ON comments.id = likes.comment_id;
참고로,
LEFT JOIN
을 안 했으면 아래의 조건들에서 null이 필연적으로 잡히므로 빈 테이블을 반환한다.
sqlSELECT date_trunc('week', COALESCE(posts.created_at, comments.created_at)) AS week, COUNT(posts.id) AS num_likes_for_posts, COUNT(comments.id) AS num_likes_for_comments FROM likes LEFT JOIN posts ON posts.id = likes.post_id LEFT JOIN comments ON comments.id = likes.comment_id GROUP BY week ORDER BY week;
이렇게 쿼리를 작성하면 실행시 약간의 시간이 걸린다. 이 때 Materialized View
를 생성하면 쿼리 결과가 저장되어 금방 결과를 얻을 수 있다.
sqlCREATE MATERIALIZED VIEW weekly_likes AS ( SELECT date_trunc('week', COALESCE(posts.created_at, comments.created_at)) AS week, COUNT(posts.id) AS num_likes_for_posts, COUNT(comments.id) AS num_likes_for_comments FROM likes LEFT JOIN posts ON posts.id = likes.post_id LEFT JOIN comments ON comments.id = likes.comment_id GROUP BY week ORDER BY week ) WITH DATA;
조회하고 싶을 땐 아래와 같이 조회한다. 성능이 훨씬 개선된 것을 볼 수 있다.
sqlSELECT * FROM weekly_likes;
Refreshing Materialized Views
하지만, 이렇게 Materialized View
를 저장하면, posts
나 comments
테이블이 업데이트되었을 때 캐싱된 데이터가 자동으로 업데이트 되진 않는다.
데이터가 바뀌면 아래와 같이 REFRESH MATERIALIZED VIEW 뷰명
키워드로 업데이트해야 한다.
sqlREFRESH MATERIALIZED VIEW weekly_likes;
따라서, Materialized View
는 가끔씩만 업데이트 하는 경우(위의 예시처럼, 한주에 한번 정도라던가)가 필요할 때 사용한다. 자주 사용되고 비싼 쿼리지만, 업데이트 자체는 가끔만 되는 경우가 최적이다.