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

고객별 마지막 주문 요약에 PK를 붙인 다음 날부터 야간 적재가 ORA-00001로 멈춘다

기초INSERT한빛유통198 / 700

상황 ​

CRM 화면의 「마지막 주문」 칸은 야간 배치가 채우는 요약 테이블을 읽는다. 배치는 요약 테이블을 비우고(TRUNCATE) 고객마다 마지막 주문 한 건을 다시 넣는다. 지난달 CRM팀이 "고객이 두세 줄씩 보인다"라고 해서 DBA가 요약 테이블에 PK를 붙였다. 그다음 날부터 배치가 ORA-00001로 멈추고, 칸은 비어 있다. 업무 규칙은 "마지막 주문은 주문일이 가장 늦은 주문, 같은 날이면 주문번호가 큰 주문"이다.

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 5,826블록 · 인덱스 없음 · ORD_DT는 전부 자정 (시분초 없음) · 고객 2,000명이 500건씩 · ORD_SEQ는 유일하다
  • 고객마다 주문이 있는 날은 219일이고 하루에 2 ~ 3건씩이다. 마지막 주문일에 주문이 2건인 고객은 1,435명, 3건인 고객은 565명이다
  • T_CUS_LAST_ORD 고객별 마지막 주문 요약 (이 문제에서 쓰는 파생 테이블): CUS_ID · LAST_ORD_SEQ · LAST_ORD_DT · LAST_ORD_AMT · BAS_DT · 지난달 붙인 PK_T_CUS_LAST_ORD (CUS_ID) · 통계 최신

원본 SQL ​

sql
INSERT INTO T_CUS_LAST_ORD (CUS_ID, LAST_ORD_SEQ, LAST_ORD_DT, LAST_ORD_AMT, BAS_DT)
SELECT o.CUS_ID, o.ORD_SEQ, o.ORD_DT, o.ORD_AMT, TRUNC(SYSDATE)
  FROM T_ORD_BIG o,
       (SELECT CUS_ID, MAX(ORD_DT) AS MAX_DT
          FROM T_ORD_BIG
         GROUP BY CUS_ID) m
 WHERE o.CUS_ID = m.CUS_ID
   AND o.ORD_DT = m.MAX_DT

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

xplan
[SELECT 부분만 떼어 돌린 실행계획]
-----------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Used-Mem |
-----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |           |      1 |        |   4565 |00:00:00.43 |   11652 |          |
|*  1 |  HASH JOIN            |           |      1 |   2000 |   4565 |00:00:00.43 |   11652 | 1321K (0)|
|   2 |   VIEW                |           |      1 |   2000 |   2000 |00:00:00.24 |    5826 |          |
|   3 |    HASH GROUP BY      |           |      1 |   2000 |   2000 |00:00:00.24 |    5826 | 1497K (0)|
|   4 |     TABLE ACCESS FULL | T_ORD_BIG |      1 |   1000K|   1000K|00:00:00.05 |    5826 |          |
|   5 |   TABLE ACCESS FULL   | T_ORD_BIG |      1 |   1000K|   1000K|00:00:00.05 |    5826 |          |
-----------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("O"."CUS_ID"="M"."CUS_ID" AND "O"."ORD_DT"="M"."MAX_DT")

[배치 로그]  ORA-00001: unique constraint (SQLP.PK_T_CUS_LAST_ORD) violated

문제 ​

  1. 고객 2,000명인데 4,565행이 나오는 까닭을 데이터와 조인 조건으로 설명하시오. 실행계획에서 같은 테이블을 몇 번 읽는지도 쓰시오.
  2. 업무 규칙대로 고객마다 한 행을 넣고, T_ORD_BIG은 한 번만 읽도록 적재 SQL을 고치시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자