Skip to content
튜닝 연습조인 튜닝
JOIN-012

PG 승인 테이블에 인덱스를 만들었는데 결제 내역 팝업이 승인 테이블을 통째로 읽는다

중급SELECT한빛유통162 / 700

상황 ​

상담 화면의 「결제 내역」 팝업은 고객 한 명의 최근 6개월 주문 옆에 PG사 승인 번호와 승인 금액을 붙여 보여 준다. 상담원이 하루 8천 번쯤 연다. 지난달 정산팀이 PG 승인 테이블의 가맹점 주문번호에 인덱스를 만들었는데, 팝업은 빨라지지 않았다. 아래는 고객 CUS_000390(최근 6개월 주문 13건)의 실행계획이다.

테이블과 인덱스 ​

  • T_ORD: 100,000행 · 896블록 · PK_T_ORD (ORD_SEQ) · IX_T_ORD_CUS_DT (CUS_ID, ORD_DT) · ORD_SEQ는 NUMBER(18)
  • T_PG_APRV PG 승인 내역 (이 문제에서 쓰는 파생 테이블): PG사가 매일 밤 보내 주는 승인 파일을 그대로 적재한다 · T_ORD와 1:1 · 100,000행 · 820블록 · APRV_NO · MRCH_ORD_NO VARCHAR2(20) · APRV_DT · APRV_AMT
  • MRCH_ORD_NO는 가맹점 주문번호다. PG사는 ORD_SEQ를 12자리 0 채움 문자열로 돌려준다 (ORD_SEQ = 390이면 '000000000390')
  • 인덱스 IX_PG_APRV_ORD (MRCH_ORD_NO): 지난달 생성 · 통계 최신

원본 SQL ​

sql
SELECT o.ORD_SEQ, o.ORD_DT, o.PAY_TP, o.PAY_AMT,
       p.APRV_NO, p.APRV_DT, p.APRV_AMT
  FROM T_ORD o, T_PG_APRV p
 WHERE o.CUS_ID = :v_cus
   AND o.ORD_DT >= :v_from
   AND p.MRCH_ORD_NO = o.ORD_SEQ
 ORDER BY o.ORD_DT DESC

실행계획 학습용 예시 ​

xplan
--------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                              | Name            | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  Used-Mem |
--------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                       |                 |      1 |        |     13 |00:00:00.03 |     836 |           |
|   1 |  SORT ORDER BY                         |                 |      1 |     13 |     13 |00:00:00.03 |     836 | 2048  (0) |
|*  2 |   HASH JOIN                            |                 |      1 |     13 |     13 |00:00:00.03 |     836 | 1195K (0) |
|   3 |    TABLE ACCESS BY INDEX ROWID BATCHED | T_ORD           |      1 |     13 |     13 |00:00:00.01 |      16 |           |
|*  4 |     INDEX RANGE SCAN                   | IX_T_ORD_CUS_DT |      1 |     13 |     13 |00:00:00.01 |       3 |           |
|   5 |    TABLE ACCESS FULL                   | T_PG_APRV       |      1 |   100K |   100K |00:00:00.02 |     820 |           |
--------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("O"."ORD_SEQ"=TO_NUMBER("P"."MRCH_ORD_NO"))
   4 - access("O"."CUS_ID"=:V_CUS AND "O"."ORD_DT">=:V_FROM)

문제 ​

  1. Predicate Information 2번 줄의 TO_NUMBER가 어디서 왔는지, 그 때문에 IX_PG_APRV_ORD를 왜 쓰지 못하는지 설명하시오.
  2. 주문 13건마다 IX_PG_APRV_ORD로 승인 건을 찾아가도록 SQL을 고치시오. 고칠 때 확인해야 할 데이터 형식과, 반대쪽을 바꾸는 방법(함수 기반 인덱스)의 위험도 서술하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자