Skip to content
튜닝 연습서브쿼리와 쿼리 변환
SUBQ-049

VIP 고객 20명의 미결제 주문을 보는 화면이 결제 대기 주문 8만 건을 모두 만든다

중급SELECT한빛유통284 / 700

상황 ​

영업팀의 「VIP 미결제 주문」 화면은 A 등급 고객 20명의 결제 대기 주문을 고객명, 대기 일수와 함께 보여 준다. 영업 담당 15명이 수시로 새로 고치는데 한 번에 0.15초쯤 걸린다. SQL을 짠 조민우는 이렇게 설명한다. "인라인 뷰는 먼저 실행되는 블록이니까, 결제 대기 주문을 먼저 뽑아 놓고 고객을 붙이려고 NO_MERGE를 넣었어요. 뷰가 풀려 버리면 순서가 엉킬까 봐서요."

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 5,826블록 · ORD_ST PENDING 8%(약 80,000건) · 고객당 약 500건, 그중 결제 대기 약 40건 · 한 고객의 주문은 테이블 곳곳에 흩어져 있다
  • 인덱스 IX_ORD_BIG_CUS_ST (CUS_ID, ORD_ST): 높이 3 · CS 화면용으로 작년에 만들었다
  • M_CUS: 2,000행 · 30블록 · PK_M_CUS (CUS_ID) · A 등급 20명 · 통계 최신

원본 SQL ​

sql
SELECT c.CUS_ID, c.CUS_NM, v.ORD_SEQ, v.ORD_DT, v.ORD_AMT,
       TRUNC(SYSDATE) - v.ORD_DT AS WAIT_DAYS
  FROM M_CUS c,
       (SELECT /*+ NO_MERGE */ ORD_SEQ, CUS_ID, ORD_DT, ORD_AMT
          FROM T_ORD_BIG
         WHERE ORD_ST = 'PENDING') v
 WHERE c.CUS_GD = 'A'
   AND v.CUS_ID = c.CUS_ID
 ORDER BY c.CUS_ID, v.ORD_DT DESC

실행계획 학습용 예시 ​

xplan
-------------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Used-Mem |
-------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |           |      1 |        |    803 |00:00:00.14 |    5856 |          |
|   1 |  SORT ORDER BY        |           |      1 |    800 |    803 |00:00:00.14 |    5856 |75776  (0)|
|*  2 |   HASH JOIN           |           |      1 |    800 |    803 |00:00:00.14 |    5856 | 1245K (0)|
|*  3 |    TABLE ACCESS FULL  | M_CUS     |      1 |     20 |     20 |00:00:00.01 |      30 |          |
|   4 |    VIEW               |           |      1 |  80000 |  80127 |00:00:00.12 |    5826 |          |
|*  5 |     TABLE ACCESS FULL | T_ORD_BIG |      1 |  80000 |  80127 |00:00:00.11 |    5826 |          |
-------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("V"."CUS_ID"="C"."CUS_ID")
   3 - filter("C"."CUS_GD"='A')
   5 - filter("ORD_ST"='PENDING')

문제 ​

  1. 4번 VIEW 줄이 결제 대기 주문 80,127건을 모두 만든 이유를 NO_MERGE와 관련지어 설명하시오. "인라인 뷰는 먼저 실행된다"는 설명이 왜 틀렸는지도 쓰시오.
  2. 고객 20명의 결제 대기 주문만 인덱스로 읽도록 SQL을 고치고, 고친 뒤의 처리 순서와 읽은 블록 수를 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자