Skip to content
튜닝 연습옵티마이저와 통계
OPT-004

반기마다 흔들리는 핵심 화면, 힌트로 박을까 프로파일을 받을까

실전SELECT한빛유통594 / 700

상황 ​

반기 보고에 '핵심 화면의 계획 관리' 항목이 한 줄 들어간다. 등급별 매출(Q2)은 지난 반기에 통계 한 번(일요일 밤의 빈 테이블 통계) 때문에 1,026,852블록을 읽은 적이 있다. 오과장의 의견은 이렇다. "USE_HASH를 박아 두면 통계가 무슨 일을 해도 해시잖아요." 정하은은 다른 안을 냈다. "튜닝 어드바이저로 SQL 프로파일을 받으면 배포 없이 계획이 고정돼요. 옛 판에 돌렸더니 99.42%라고 나왔어요." 박팀장은 이렇게 정리했다. "무엇으로 지킬지, 근거를 붙여서."

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 5,826블록 · 매주 일요일 재적재 · 인덱스 셋
  • M_CUS: 2,000행 · 30블록 · PK_M_CUS · M_RGN: 8행
  • Q2 rev01(06화, 힌트 없음): 좋은 계획 HASH JOIN 2292855265 · 5,868블록 / 나쁜 계획 NESTED LOOPS · 1,026,852블록
  • Q2 rev00(옛 판): /*+ LEADING(o c) USE_NL(c) */가 박혀 있던 2018년 소스
  • Oracle Free · CONTROL_MANAGEMENT_PACK_ACCESS = DIAGNOSTIC+TUNING(운영 라이선스는 확인 중)
  • 아래 측정은 복사본(T_ORD_BIG_C18)과 세션 설정, 메모리 설정에서만 했다.

원본 SQL ​

sql
-- 오과장 안 — Q2 rev01 에 조인 순서 · 방법을 박는다
SELECT /*+ LEADING(c o) USE_HASH(o) */
       c.CUS_GD, COUNT(*) AS ord_cnt, SUM(o.ORD_AMT) AS amt,
       MAX((SELECT r.RGN_NM FROM M_RGN r WHERE r.RGN_ID = c.RGN_ID)) AS rgn_sample
  FROM T_ORD_BIG o, M_CUS c
 WHERE c.CUS_ID = o.CUS_ID
 GROUP BY c.CUS_GD;

-- 정하은 안 — 튜닝 어드바이저의 권고 프로파일을 받는다 (배포 없음)
EXEC DBMS_SQLTUNE.ACCEPT_SQL_PROFILE(task_name => 'T18_R0_Q2', name => 'PROF_T18_Q2');

실행계획 실측 · 교재 18화(복사본) ​

xplan
[① 힌트 — 06화 회의록]
  2018.11  LEADING(o c) USE_NL(c) · "3초 → 0.4초" · 첨부 끝 줄 "측정 조건 : 주문 20,000 건"
  2024.04  같은 힌트 · 주문 1,000,000 건 → 1,026,849 블록 (힌트를 떼자 5,869)

[② SQL 프로파일 — 튜닝 어드바이저 (옛 판 rev00 에 돌림)]
  권고                    SQL PROFILE × 1 · Buffer Gets 1,026,849 → 5,868 (99.42 %)
  프로파일 안의 힌트      OPTIMIZER_FEATURES_ENABLE(default) · IGNORE_OPTIM_EMBEDDED_HINTS   (두 줄뿐)
  받은 뒤                 HASH JOIN · 5,869 · Note: SQL profile PROF_T18_Q2 used · 소스에는 USE_NL 이 그대로
  팩 설정을 DIAGNOSTIC 으로 (메모리에서만) 내리고 커서를 지운 뒤
                          에러 없음 · NESTED LOOPS · 1026K · Note 에서 프로파일 줄이 사라짐
  같은 설정에서 베이스라인  쓰인다 (SQL plan baseline used)

[③ SQL plan baseline — 복사본]
  장면 B (Q2 꼴)
   [4] 정상 통계 · HASH 를 커서 캐시에서 올림     HASH JOIN     5,863   MANUAL-LOAD · ACCEPTED YES
   [5] 빈 테이블 통계 (NUM_ROWS 0 · 실제 100만)   HASH JOIN     5,868   E-Rows 1 · Note: SQL plan baseline used
                                                                     · 대기 줄에 NL (AUTO-CAPTURE · ACCEPTED NO)
   [6] 내 세션만 베이스라인 끔                     NESTED LOOPS  1026K
   [7] 대기 줄의 NL 을 진화                        "failed the benefit criterion ... 0.33281 times worse" → 대기 줄에 남음
  장면 A (Q1 꼴 · 인덱스가 없을 때의 FULL 을 올림)
   [1] FULL 을 베이스라인으로                      TABLE ACCESS FULL   5,821
   [2] (ORD_DT, ORD_AMT) 인덱스를 만듦             여전히 FULL 5,821 · 대기 줄에 INDEX RANGE SCAN (ACCEPTED NO)
   [3] 진화                                        "passed the benefit criterion ... 63.70970 times better" → INDEX RANGE SCAN 91
  자동 진화 (Free · 루트)                          ORA-38153: Software edition is incompatible with SQL plan management.

문제 ​

  1. 세 장치(힌트, SQL 프로파일, SQL plan baseline)를 '어디에 있는가, 새 계획이 더 나은지 검사하는가, 무엇이 그 장치를 꺼뜨리는가'의 세 기준으로 비교하시오.
  2. 반기마다 일어나는 통계 변화로부터 Q2를 지킬 방법을 하나 고르고 SQL로 쓰시오.
  3. 고른 방법이 막지 못하는 것과, 그 방법을 유지하는 절차(누가, 언제, 무엇을 함께 적는지)를 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자