Skip to content
튜닝 연습소트 튜닝과 페이징
SORT-068

10분마다 도는 매장 일별 판매 MV 새로 고침 잡이 유통 DB 논리 읽기 1위다

중급DDL유통373 / 700

상황 ​

본사 영업지원팀의 「매장 일별 판매 현황」 화면은 작년에 만든 구체화 뷰 MV_SHP_DAY를 직접 읽어 바로 뜬다. 숫자가 늦지 않게 07:00 ~ 21:00에 10분마다 COMPLETE로 새로 고치는 잡을 걸어 두었다(하루 84번). DBA가 보니 AWR 논리 읽기 1위가 이 잡이고, 새로 고침 한 번에 3.4초와 redo 1.9MB를 쓴다. 판매는 10분에 평균 5건(판매상품 약 11줄) 들어온다. 오과장은 "10분 사이에 바뀌는 건 열 줄 남짓인데 왜 매번 처음부터 다시 만드나"라고 묻는다.

테이블과 인덱스 ​

  • CF10 판매: 500,000행 · 4,583블록(전체 스캔 4,510) · SLE_NO(PK) · SLE_DT · SHP_NO
  • CF11 판매상품: 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO) · SLE_QTY · SLE_UPRC
  • MV_SHP_DAY: 3,650행(730일 × 매장 5곳) · 25블록 · 아래 DDL · 원장에 MV 로그는 없다
  • 판매 등록은 POS 연동 프로그램이 판매 한 건(CF10 1줄 + CF11 평균 2.2줄)을 한 트랜잭션으로 넣는다 · 하루 약 700건 · 지난 판매의 수량 정정(CF11 UPDATE)이 하루 수십 건
  • 이 MV를 읽는 것은 「매장 일별 판매 현황」 화면 하나다

원본 SQL ​

sql
CREATE MATERIALIZED VIEW MV_SHP_DAY
  BUILD IMMEDIATE
  REFRESH COMPLETE ON DEMAND
AS
SELECT h.SLE_DT, h.SHP_NO,
       COUNT(*)                    AS LINE_CNT,
       SUM(d.SLE_QTY)              AS QTY,
       SUM(d.SLE_QTY * d.SLE_UPRC) AS AMT
  FROM CF10 h, CF11 d
 WHERE d.SLE_NO = h.SLE_NO
 GROUP BY h.SLE_DT, h.SHP_NO;

-- 10분마다 (07:00 ~ 21:00)
BEGIN
  DBMS_MVIEW.REFRESH('MV_SHP_DAY', method => 'C');
END;

실행계획 학습용 예시 ​

xplan
[새로 고침 한 번 · 잡 세션의 통계 차이]
  session logical reads        13,190
  db block changes              7,642
  redo size                 1,962,404
  undo change vector size     612,880
  경과 시간                       3.4초

[새로 고침 안의 INSERT … SELECT]
---------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Used-Mem |
---------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT         |            |      1 |        |      0 |00:00:03.21 |   13120 |          |
|   1 |  LOAD TABLE CONVENTIONAL | MV_SHP_DAY |      1 |        |      0 |00:00:03.21 |   13120 |          |
|   2 |   HASH GROUP BY          |            |      1 |   3650 |   3650 |00:00:03.05 |   12714 | 1123K (0)|
|*  3 |    HASH JOIN             |            |      1 |   1096K|   1096K|00:00:02.71 |   12714 |   31M (0)|
|   4 |     TABLE ACCESS FULL    | CF10       |      1 |    500K|    500K|00:00:00.05 |    4510 |          |
|   5 |     TABLE ACCESS FULL    | CF11       |      1 |   1096K|   1096K|00:00:00.12 |    8204 |          |
---------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access("D"."SLE_NO"="H"."SLE_NO")

[그 앞의 DELETE FROM MV_SHP_DAY]  3,650행 · Buffers 70 (기본 COMPLETE 새로 고침은 지우고 다시 넣는 한 트랜잭션이다)

문제 ​

  1. 새로 고침 한 번이 13,190블록과 redo 1.9MB를 쓰는 까닭을 COMPLETE 새로 고침이 하는 일로 설명하시오.
  2. 10분 사이에 바뀐 판매만 반영하도록 MV와 MV 로그를 다시 만들고, 빠른 새로 고침이 되려면 MV에 무엇이 더 있어야 하는지 쓰시오.
  3. 바꾼 뒤 판매 등록 쪽과 운영에서 생기는 대가를 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자