테마
CRM 화면의 「마지막 주문」 칸은 야간 배치가 채우는 요약 테이블을 읽는다. 배치는 요약 테이블을 비우고(TRUNCATE) 고객마다 마지막 주문 한 건을 다시 넣는다.
지난달 CRM팀이 "고객이 두세 줄씩 보인다"라고 해서 DBA가 요약 테이블에 PK를 붙였다. 그다음 날부터 배치가 ORA-00001로 멈추고, 칸은 비어 있다. 업무 규칙은 "마지막 주문은 주문일이 가장 늦은 주문, 같은 날이면 주문번호가 큰 주문"이다.
T_ORD_BIG: 1,000,000행 · 5,826블록 · 인덱스 없음 · ORD_DT는 전부 자정 (시분초 없음) · 고객 2,000명이 500건씩 · ORD_SEQ는 유일하다T_CUS_LAST_ORD 고객별 마지막 주문 요약 (이 문제에서 쓰는 파생 테이블): CUS_ID · LAST_ORD_SEQ · LAST_ORD_DT · LAST_ORD_AMT · BAS_DT · 지난달 붙인 PK_T_CUS_LAST_ORD (CUS_ID) · 통계 최신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
[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
T_ORD_BIG은 한 번만 읽도록 적재 SQL을 고치시오.