<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>CWLog - database</title>
    <subtitle>개발 &amp; 해킹 좋아하는 사람의 블로그</subtitle>
    <link rel="self" type="application/atom+xml" href="https://blog.devcw.xyz/tags/database/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://blog.devcw.xyz/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-07-12T00:00:00+00:00</updated>
    <id>https://blog.devcw.xyz/tags/database/atom.xml</id>
    <entry xml:lang="en">
        <title>Materialized View</title>
        <published>2026-07-12T00:00:00+00:00</published>
        <updated>2026-07-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.devcw.xyz/posts/materialized-view/"/>
        <id>https://blog.devcw.xyz/posts/materialized-view/</id>
        
        <content type="html" xml:base="https://blog.devcw.xyz/posts/materialized-view/">&lt;p&gt;흔히 온라인 게임 랭킹에서 볼 수 있는 이 순위표, 다들 한번 쯤 본 적이 있을 것이다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;..&#x2F;..&#x2F;images&#x2F;valorant-ranking.jpg&quot; alt=&quot;ranking-image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;게임 &#x27;발로란트&#x27;의 랭킹 순위표&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;근래에 재미있는 릴스를 봤는데 이런 랭킹을 구현하려면 &lt;code&gt;Redis&lt;&#x2F;code&gt; 같은 캐시 서버를 써서 결과를 &#x27;캐시&#x27;하라는 내용이다. (대충 브레인랏 형식으로 설명하는 릴스) 물론 틀린 말은 아닌데 이러면 사실 복잡도를 의존하게 된다. 뿐만 아니라 추후 관리 포인트도 늘 수 있어서.. 별로 좋은 생각은 아닌 것 같다.&lt;&#x2F;p&gt;
&lt;p&gt;관리 포인트를 줄여주면서 데이터베이스에서 기본적으로 제공해주는 기능중에 &lt;strong&gt;Materialized View&lt;&#x2F;strong&gt; 라는 유용한 기능이 있다. 직역하자면 &lt;strong&gt;구체화된 뷰&lt;&#x2F;strong&gt;라는 뜻인데, 쿼리 결과를 미리 계산해서 테이블 형태로 저장한다. 즉, 랭킹 뿐만 아니라 어떤 큰 쿼리 집계(e.g 대쉬보드, 사용량 분석 등등..)에 맞는 기능이다.&lt;&#x2F;p&gt;
&lt;p&gt;이게 한번 계산한 테이블은 영구적이라, 특정 주기나 수동으로 Resync가 필요하다. 그러니까 어떤 트리거가 없으면 원본 테이블에 변화가 있어도 계산된 값은 바뀌지 않는다.&lt;&#x2F;p&gt;
&lt;p&gt;대표적으로 &lt;strong&gt;MV&lt;&#x2F;strong&gt;를 지원하는 데이터베이스 엔진은 &lt;code&gt;Oracle&lt;&#x2F;code&gt;이랑 &lt;code&gt;PostgreSQL&lt;&#x2F;code&gt;이 있다. 해당 글에서는 &lt;code&gt;PostgreSQL&lt;&#x2F;code&gt; 기준으로 설명한다.&lt;&#x2F;p&gt;
&lt;p&gt;직접 한번 만들어보자.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;developer@arch-b9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; ~&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt;-name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; mv-demo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; POSTGRES_PASSWORD=postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; 5432:5432&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; postgres:18&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;b5d221c60831c7017f01500decff8f172f3d0c9322330a592256485a31296988&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;developer@arch-b9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; ~&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; %&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;이렇게 18버전 서버를 하나 띄우고, 간단한 스코어 테이블을 만들고 값들을 채워보자.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;developer@arch-b9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; ~&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; exec&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt;it&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; mv-demo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; psql&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt;U&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; postgres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;psql&lt;&#x2F;span&gt;&lt;span&gt; (18.1 (Debian&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; 18.1-1.pgdg13+2&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt;help&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; help.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;# CREATE TABLE game_scores (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; INT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; PRIMARY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; KEY,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    username&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; TEXT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; NOT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; NULL,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    score&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; INT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; NOT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;# INSERT INTO game_scores VALUES&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;1,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;alice&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;,1500&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;,(2,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;bob&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;,2300&lt;&#x2F;span&gt;&lt;span&gt;),(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;3,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;carol&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;,1800&lt;&#x2F;span&gt;&lt;span&gt;),(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;4,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;dave&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;,900&lt;&#x2F;span&gt;&lt;span&gt;),(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;5,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;erin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;,2100&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;INSERT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;그리고 이제 저 데이터들을 가지고 MV를 만들어보겠다. (실제 프로덕션 테이블엔 컬럼도 훨씬 많고 복잡할 것이다.)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;# CREATE MATERIALIZED VIEW ranking AS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; ROW_NUMBER&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; OVER&lt;&#x2F;span&gt;&lt;span&gt; (ORDER&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; BY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; score&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; DESC&lt;&#x2F;span&gt;&lt;span&gt;) AS rank, user_id, username, score&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; game_scores&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;이러면 &lt;code&gt;ranking&lt;&#x2F;code&gt;이란 이름을 가진 뷰가 완성이 되는데, 한번 찍어보자.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;# SELECT &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; FROM ranking ORDER BY rank&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; rank&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; username&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; score&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;------+---------+----------+-------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; bob&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;      |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;  2300&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; erin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;     |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;  2100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; carol&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;  1800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; alice&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;  1500&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; dave&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;     |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;   900&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; rows&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;이렇게 잘 나오는 것을 볼 수 있다. 원본을 한번 바꾸고 다시 조회해보자.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;# UPDATE game_scores SET score = 9999 WHERE user_id = 4&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;UPDATE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;# SELECT &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; FROM ranking ORDER BY rank&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; rank&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; username&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; score&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;------+---------+----------+-------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; bob&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;      |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;  2300&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; erin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;     |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;  2100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; carol&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;  1800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; alice&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;  1500&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; dave&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;     |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;   900&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; rows&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;보면 옛날 랭킹이 그대로 나오는 것을 확인할 수 있다. 이제 refresh를 해주면..&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;# REFRESH MATERIALIZED VIEW ranking&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;# SELECT &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; FROM ranking&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; rank&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; username&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; score&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;------+---------+----------+-------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; dave&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;     |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;  9999&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; bob&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;      |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;  2300&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; erin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;     |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;  2100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; carol&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;  1800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;       1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; alice&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;  1500&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; rows&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;이렇게 갱신하면 제대로 나오는 걸 볼 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;문제는, 리프레시할 때 뷰를 재계산하기 때문에 해당 MV는 락이 걸려 조회할 수 없다. 이를 해결하기 위해 &lt;strong&gt;CONCURRENTLY&lt;&#x2F;strong&gt; 라는 옵션이 있는데 이건 새로 계산하고 거기서 &lt;strong&gt;diff&lt;&#x2F;strong&gt; 계산을 또 한다. 그리고 바뀐 행만 반영한다.&lt;&#x2F;p&gt;
&lt;p&gt;아무래도 중간에 바뀐 걸 비교하고 스왑하니까 좀 더 비용적으로 무거운데, 읽기가 절대 막히면 안되는 상황에서 쓸만하다. 다만, 저거 하려면 유니크 인덱스가 필요하다.&lt;&#x2F;p&gt;
&lt;p&gt;대강 알아봤는데 실무에선 pgcron 같은거 묶어서 쓸 것 같다. 좋은 기능이다.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
