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

어드바이저 권고 프로파일을 받아들였는데 이튿날 밤 정산 대사가 다시 느리다

기초PLSQL한빛유통628 / 700

상황 ​

정산팀은 외부 업체의 정산 대사 솔루션을 쓴다. 솔루션은 결제일을 리터럴로 박은 SQL을 날짜마다 새로 만들어 보내고, SQL 맨 앞에는 업체가 넣은 힌트가 있다. 매일 밤 지난 30일을 하루씩 다시 대사하므로 같은 모양의 문장이 30개 돈다. 그제 DBA가 6월 15일 문장에 튜닝 어드바이저를 돌려 권고 프로파일을 받아들였다. 그 문장은 0.58초 → 0.01초가 됐다. 그런데 어젯밤 대사에서는 6월 15일 문장만 빨랐고 나머지 29개는 그대로였다.

테이블과 인덱스 ​

  • T_ORD: 100,000행 · 896블록 · PK_T_ORD (ORD_SEQ) 높이 2 · PAY_DT DATE(시분초 있음) · 결제일 하루 약 90건 · 하루치 결제는 90블록에 흩어져 있다
  • 인덱스 IX_T_ORD_PAY_DT (PAY_DT)
  • T_ORD_DET: 200,000행 · 896블록 · PK_T_ORD_DET (ORD_SEQ, ORD_DET_NO) 높이 2 · 주문당 평균 2건
  • Tuning Pack 계약 있음(CONTROL_MANAGEMENT_PACK_ACCESS = DIAGNOSTIC+TUNING) · CURSOR_SHARING = EXACT

원본 SQL ​

sql
-- 솔루션이 날짜마다 만들어 보내는 문장 (6월 16일 판)
SELECT /*+ ORDERED USE_NL(o) */
       o.ORD_SEQ, o.PAY_DT, o.PAY_TP, o.PAY_AMT, d.ITM_ID, d.ORD_QTY, d.UNT_PRC
  FROM T_ORD_DET d, T_ORD o
 WHERE o.ORD_SEQ = d.ORD_SEQ
   AND o.PAY_DT >= TO_DATE('20240616', 'YYYYMMDD')
   AND o.PAY_DT <  TO_DATE('20240617', 'YYYYMMDD');

-- 그제 DBA 가 받아들인 권고
EXEC DBMS_SQLTUNE.ACCEPT_SQL_PROFILE(task_name => 'TASK_RECON_0615', name => 'PROF_RECON_0615');

실행계획 학습용 예시 · 교재 18화의 프로파일 모양 ​

xplan
[어젯밤 — 6월 16일 문장]
---------------------------------------------------------------------------------------------
| Id  | Operation                    | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |           |      1 |        |    182 |00:00:00.58 |     601K|
|   1 |  NESTED LOOPS                |           |      1 |    180 |    182 |00:00:00.58 |     601K|
|   2 |   NESTED LOOPS               |           |      1 |    200K|    200K|00:00:00.36 |     401K|
|   3 |    TABLE ACCESS FULL         | T_ORD_DET |      1 |    200K|    200K|00:00:00.02 |     896 |
|*  4 |    INDEX UNIQUE SCAN         | PK_T_ORD  |    200K|      1 |    200K|00:00:00.21 |     400K|
|*  5 |   TABLE ACCESS BY INDEX ROWID| T_ORD     |    200K|      1 |    182 |00:00:00.19 |     200K|
---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   4 - access("O"."ORD_SEQ"="D"."ORD_SEQ")
   5 - filter(("O"."PAY_DT">=TO_DATE(' 2024-06-16 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
              "O"."PAY_DT"<TO_DATE(' 2024-06-17 00:00:00', 'syyyy-mm-dd hh24:mi:ss')))

[같은 밤 — 6월 15일 문장]  IX_T_ORD_PAY_DT → PK_T_ORD_DET 의 NL · Buffers 381
  Note
  -----
     - SQL profile PROF_RECON_0615 used for this statement

[DBA_SQL_PROFILES]
 NAME              CATEGORY  STATUS   FORCE_MATCHING  CREATED
 PROF_RECON_0615   DEFAULT   ENABLED  NO              06-17 09:12
 (프로파일 안의 힌트 : OPTIMIZER_FEATURES_ENABLE(default) · IGNORE_OPTIM_EMBEDDED_HINTS)

[V$SQL — 어젯밤 대사 문장 가운데 셋]
 결제일  SQL_ID         EXACT_MATCHING_SIGNATURE  FORCE_MATCHING_SIGNATURE  SQL_PROFILE       BUFFER_GETS
 06-15   4m1kq8z0v7c2a   1438207716409352211       8806217430295501273       PROF_RECON_0615           381
 06-16   9cz2w5r1h3n8d   6192774035518093160       8806217430295501273       (없음)                601,014
 06-17   2bx6t0y4p9m1f   3370951182604277725       8806217430295501273       (없음)                600,988

문제 ​

  1. 프로파일이 6월 15일 문장에만 붙은 이유를 V$SQL의 두 서명 칸으로 설명하시오. 프로파일이 붙은 문장이 왜 빨라졌는지도 쓰시오.
  2. 30개 문장 모두에 프로파일이 붙도록 고치고, 이 방법의 한계와 근본 해결을 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자