테마
지난주 DBA가 경영지원팀의 「월별 매출」 대시보드(1분마다 새로 고침, 하루 약 720번)를 빠르게 하려고 구체화 뷰 MV_ORD_MON을 만들고 쿼리 재작성(Query Rewrite)을 켰다. 화면 SQL은 손대지 않았다. 월요일 08:50에 재 보니 3블록이었는데, 오후에 AWR을 보니 이 SQL이 실행마다 5,826블록을 읽고 있었다.
대시보드 요구서에는 "어제까지의 숫자면 된다"라고 적혀 있다. 주문은 9시 무렵부터 낮 동안 계속 들어온다(하루 약 900건). MV는 매일 02:00 잡이 새로 고친다.
T_ORD_BIG: 1,000,000행 · 5,826블록 · ORD_ST COMPLETE 90% · PENDING 8% · CANCEL 2% · 이 문제에서는 인덱스가 없다 · 낮 동안 주문이 계속 INSERT, COMMIT된다MV_ORD_MON 구체화 뷰: 아래 DDL · 108행(36개월 × 상태 3) · 3블록 · 매일 02:00 DBMS_MVIEW.REFRESH('MV_ORD_MON', 'C')QUERY_REWRITE_ENABLED = TRUE · QUERY_REWRITE_INTEGRITY = ENFORCED(기본값)-- 지난주 DBA 가 만든 MV
CREATE MATERIALIZED VIEW MV_ORD_MON
BUILD IMMEDIATE
REFRESH COMPLETE ON DEMAND
ENABLE QUERY REWRITE
AS
SELECT TRUNC(ORD_DT, 'MM') AS ORD_MM, ORD_ST,
COUNT(*) AS ORD_CNT, SUM(ORD_AMT) AS ORD_AMT
FROM T_ORD_BIG
GROUP BY TRUNC(ORD_DT, 'MM'), ORD_ST;
-- 대시보드 SQL (손대지 않았다)
SELECT TRUNC(ORD_DT, 'MM') AS ORD_MM,
COUNT(*) AS ORD_CNT, SUM(ORD_AMT) AS ORD_AMT
FROM T_ORD_BIG
WHERE ORD_ST <> 'CANCEL'
GROUP BY TRUNC(ORD_DT, 'MM')
ORDER BY ORD_MM
[월요일 08:50 · 새로 고침 뒤 아직 주문이 없을 때]
-------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 36 |00:00:00.01 | 3 |
| 1 | SORT GROUP BY | | 1 | 36 | 36 |00:00:00.01 | 3 |
|* 2 | MAT_VIEW REWRITE ACCESS FULL| MV_ORD_MON | 1 | 72 | 72 |00:00:00.01 | 3 |
-------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("MV_ORD_MON"."ORD_ST"<>'CANCEL')
[월요일 14:10 · 같은 SQL]
-------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
-------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 36 |00:00:00.31 | 5826 | |
| 1 | SORT GROUP BY | | 1 | 36 | 36 |00:00:00.31 | 5826 | 4096 (0)|
|* 2 | TABLE ACCESS FULL| T_ORD_BIG | 1 | 980K| 980K|00:00:00.11 | 5826 | |
-------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("ORD_ST"<>'CANCEL')
[14:10 · USER_MVIEWS] MVIEW_NAME MV_ORD_MON · REWRITE_ENABLED Y · STALENESS STALE · LAST_REFRESH_DATE 06/24 02:00:41
QUERY_REWRITE_INTEGRITY로 설명하시오.QUERY_REWRITE_INTEGRITY를 STALE_TOLERATED로 바꾸는 안과 견주시오.