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

취소 주문 정산 점검은 취소가 많은 고객일수록 느리다

중급SELECT한빛유통593 / 700

상황 ​

정산팀의 「취소 주문 정산 점검」 화면은 고객 번호를 넣으면 그 고객의 취소 주문 가운데 정산에 들어간 주문을 보여 준다(취소는 정산되면 안 된다). 조민우가 말했다. "취소가 많은 고객일수록 느려요. 상담 중에 수십 번 누르는 화면이에요." 6월에는 T_ORD의 상태별 조회 화면 때문에 ORD_ST에 히스토그램을 걸었다(10화 정책서 1호와 같은 모양의 선호도).

테이블과 인덱스 ​

  • T_ORD: 100,000행 · 896블록 · PK_T_ORD (ORD_SEQ) · 고객 2,000명 × 50건 · ORD_ST COMPLETE 90,000 · PENDING 8,000 · CANCEL 2,000(FREQUENCY 히스토그램) · CUS_ID는 히스토그램 없음
  • 이 데이터는 고객마다 상태가 하나뿐이다. (CUS_ID, ORD_ST) 조합은 2,000종으로 고객 수와 같고, 취소 고객 40명의 주문 50건은 전부 CANCEL이다.
  • T_ORD_STLM: 100,000행 · 640블록 · T_ORD의 주문마다 한 건(ORD_SEQ) · 인덱스 없음(매일 밤 비우고 다시 싣는다)
  • 확장 통계 없음 · 선호도 FOR ALL COLUMNS SIZE 1 FOR COLUMNS SIZE 254 ORD_ST

원본 SQL ​

sql
SELECT o.ORD_SEQ, o.ORD_DT, o.ORD_AMT, s.STLM_SEQ, s.STLM_DT, s.STLM_AMT
  FROM T_ORD o, T_ORD_STLM s
 WHERE o.CUS_ID = :cus
   AND o.ORD_ST = 'CANCEL'
   AND s.ORD_SEQ = o.ORD_SEQ

실행계획 학습용 예시 · 교재 10화의 상관 컬럼 ​

xplan
[:cus = 'CUS_000051' (취소 고객) · 그날 아침 첫 조회로 태어난 자식 0 을 그대로 쓴다]
------------------------------------------------------------------------------------------
| Id  | Operation          | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |            |      1 |        |     50 |00:00:00.17 |   32896 |
|   1 |  NESTED LOOPS      |            |      1 |      1 |     50 |00:00:00.17 |   32896 |
|*  2 |   TABLE ACCESS FULL| T_ORD      |      1 |      1 |     50 |00:00:00.01 |     896 |
|*  3 |   TABLE ACCESS FULL| T_ORD_STLM |     50 |      1 |     50 |00:00:00.16 |   32000 |
------------------------------------------------------------------------------------------

Peeked Binds (identified by position):
--------------------------------------
   1 - :CUS (VARCHAR2(32), CSID=873): 'CUS_000002'

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(("O"."CUS_ID"=:CUS AND "O"."ORD_ST"='CANCEL'))
   3 - filter("S"."ORD_SEQ"="O"."ORD_SEQ")

[USER_TAB_COL_STATISTICS — T_ORD]
 COLUMN_NAME   NUM_DISTINCT  HISTOGRAM
 CUS_ID                2000  NONE
 ORD_ST                   3  FREQUENCY   (CANCEL 2,000 · COMPLETE 90,000 · PENDING 8,000)

문제 ​

  1. 2번 줄의 E-Rows 1을 손으로 계산하고, 실제 50과 왜 다른지 데이터로 설명하시오. 그 1 때문에 계획에서 무엇을 선택했는지도 쓰시오.
  2. SQL은 고치지 않고 통계로 E-Rows를 바로잡으시오. 처음 만든 통계가 쓰이지 않는 함정이 하나 있다. 힌트나 인덱스로 푸는 방법과도 비교하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자