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

결제 독촉 대상이 80건으로 줄었는데 독촉 목록 SQL은 여전히 읽은 블록 수 1위다

중급UPDATE한빛유통601 / 700

상황 ​

7월부터 30일 넘게 결제 대기(PENDING)인 주문을 자동으로 취소하는 월 배치가 매달 1일 01:00에 돈다. 7월 1일 첫 실행에서 PENDING 8,000건 가운데 7,920건이 CANCEL로 바뀌었다. 상담팀의 「결제 독촉」 목록은 상담원 40명이 하루 약 6,000번 연다. 목록은 80건으로 줄었는데 화면 속도는 그대로이고, 7월 2일 AWR에서도 이 SQL이 Buffer Gets 1위다. 오과장: "통계는 밤마다 자동으로 모이잖아요."

테이블과 인덱스 ​

  • T_ORD: 100,000행 · 896블록 · PK_T_ORD (ORD_SEQ) · IX_T_ORD_ST_DT (ORD_ST, ORD_DT)(리프 약 300블록)
  • ORD_ST 실제 분포(자동 취소 뒤): COMPLETE 90,000 · CANCEL 9,920 · PENDING 80
  • 통계: 6월 29일(토) 자동 수집 · ORD_ST FREQUENCY 히스토그램(COMPLETE 90,000 · PENDING 8,000 · CANCEL 2,000) · STALE_PERCENT 10(기본값)
  • M_CUS: 2,000행 · 30블록 · PK_M_CUS
  • 자동 통계 수집 창: 평일 22:00부터 4시간 · 주말 06:00부터 20시간

원본 SQL ​

sql
-- 매달 1일 01:00 · 자동 취소 배치 (7월부터)
UPDATE T_ORD
   SET ORD_ST = 'CANCEL'
 WHERE ORD_ST = 'PENDING'
   AND ORD_DT < TRUNC(SYSDATE) - 30;
COMMIT;

-- 상담 화면 「결제 독촉」 (하루 약 6,000번)
SELECT o.ORD_SEQ, o.CUS_ID, c.CUS_NM, o.ORD_DT, o.ORD_AMT
  FROM T_ORD o, M_CUS c
 WHERE o.ORD_ST = 'PENDING'
   AND c.CUS_ID = o.CUS_ID
 ORDER BY o.ORD_DT

실행계획 학습용 예시 ​

xplan
[7월 2일 10:00 · 「결제 독촉」]
----------------------------------------------------------------------------------------------------
| Id  | Operation           | Name   | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Used-Mem |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |        |      1 |        |     80 |00:00:00.03 |     926 |          |
|   1 |  SORT ORDER BY      |        |      1 |   8000 |     80 |00:00:00.03 |     926 | 9216  (0)|
|*  2 |   HASH JOIN         |        |      1 |   8000 |     80 |00:00:00.03 |     926 | 1269K (0)|
|   3 |    TABLE ACCESS FULL| M_CUS  |      1 |   2000 |   2000 |00:00:00.01 |      30 |          |
|*  4 |    TABLE ACCESS FULL| T_ORD  |      1 |   8000 |     80 |00:00:00.02 |     896 |          |
----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("C"."CUS_ID"="O"."CUS_ID")
   4 - filter("O"."ORD_ST"='PENDING')

[USER_TAB_STATISTICS · USER_TAB_MODIFICATIONS — T_ORD · 7월 2일 10:00]
 NUM_ROWS  LAST_ANALYZED   STALE_STATS   INSERTS   UPDATES   DELETES
  100,000  06-29 07:12     NO                  0     7,920         0

문제 ​

  1. 4번 줄의 E-Rows 8,000이 어디서 왔는지 쓰고, 자동 수집이 이틀 밤을 돌았는데도 그 숫자가 그대로인 까닭을 쓰시오.
  2. 같은 일이 매달 생기지 않도록 배치를 고치시오. 고친 뒤의 계획과 일량도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자