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

하루치 주문 137건에 정산 금액을 붙이는데 정산 테이블을 6,850번 찾아간다

중급SELECT한빛유통163 / 700

상황 ​

정산팀의 「결제일 대사」 화면은 결제일 하나를 고르면 그날 결제된 주문마다 주문 금액과 정산 금액을 나란히 보여 준다. 월말에는 날짜를 바꿔 가며 하루 수백 번 돌린다. 정산 테이블에는 「고객별 정산 내역」 화면을 위해 만든 고객 번호 인덱스가 하나 있다. 개발자는 조인 조건에 고객 번호와 주문 번호를 모두 적었으니 인덱스를 잘 쓸 것이라고 했다. 아래는 결제일 2024-06-14(주문 137건)의 실행계획이다.

테이블과 인덱스 ​

  • T_ORD: 100,000행 · 896블록 · PK_T_ORD (ORD_SEQ) · IX_T_ORD_PAY (PAY_DT) · PAY_DT는 시분초 없는 날짜 · 하루 137건 · 고객마다 50건
  • T_ORD_STLM 정산: 100,000행 · 640블록 · 주문 한 건에 정산 한 건 · 야간 배치가 TRUNCATE 뒤 T_ORD 순서대로 적재한다 · 한 고객의 정산 50건은 테이블 전체에 흩어져 있다
  • 인덱스 IX_STLM_CUS (CUS_ID): 「고객별 정산 내역」 화면용 · 리프 약 280블록 · 통계 최신

원본 SQL ​

sql
SELECT o.ORD_SEQ, o.CUS_ID, o.PAY_TP, o.PAY_AMT, s.STLM_SEQ, s.STLM_AMT,
       CASE WHEN s.STLM_AMT <> o.PAY_AMT THEN 'Y' END AS diff_yn
  FROM T_ORD o, T_ORD_STLM s
 WHERE o.PAY_DT  = :v_pay_dt
   AND s.CUS_ID  = o.CUS_ID
   AND s.ORD_SEQ = o.ORD_SEQ

실행계획 학습용 예시 · 행 수는 실데이터 ​

xplan
-----------------------------------------------------------------------------------------------------------------
| Id  | Operation                              | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                       |              |      1 |        |    137 |00:00:00.04 |    7263 |
|   1 |  NESTED LOOPS                          |              |      1 |    137 |    137 |00:00:00.04 |    7263 |
|   2 |   NESTED LOOPS                         |              |      1 |   6850 |   6850 |00:00:00.01 |     413 |
|   3 |    TABLE ACCESS BY INDEX ROWID BATCHED | T_ORD        |      1 |    137 |    137 |00:00:00.01 |     139 |
|*  4 |     INDEX RANGE SCAN                   | IX_T_ORD_PAY |      1 |    137 |    137 |00:00:00.01 |       2 |
|*  5 |    INDEX RANGE SCAN                    | IX_STLM_CUS  |    137 |     50 |   6850 |00:00:00.01 |     274 |
|*  6 |   TABLE ACCESS BY INDEX ROWID          | T_ORD_STLM   |   6850 |      1 |    137 |00:00:00.03 |    6850 |
-----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   4 - access("O"."PAY_DT"=:V_PAY_DT)
   5 - access("S"."CUS_ID"="O"."CUS_ID")
   6 - filter("S"."ORD_SEQ"="O"."ORD_SEQ")

문제 ​

  1. 6번 줄의 Starts와 A-Rows, Predicate Information 5번과 6번을 보고, 조인 조건 두 개가 각각 어디서 쓰였는지 설명하시오.
  2. 인덱스를 새로 만들지, 기존 인덱스를 고칠지 정하고 개선안(DDL과 SQL)을 작성하시오. 「고객별 정산 내역」 화면과 야간 적재에 주는 영향도 함께 서술하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자