테마
한빛유통은 택배사 다섯 곳이 보내는 배송 상태 파일을 10분마다 받아 주문별 배송 추적 테이블에 반영한다. 고객센터 화면과 주문 조회 화면이 이 테이블을 읽는다. DBA가 주간 AWR을 보다가 「SQL ordered by Executions」의 1위와 2위가 이 프로그램의 UPDATE와 INSERT인 것을 찾았다. 그 시간대에는 주문 화면과 CPU를 나눠 쓴다. 개발자는 이렇게 말한다. "FORALL로 묶으면 어느 주문이 UPDATE 0건이었는지 알 수 없어서 루프로 뒀어요."
T_DLV_RCV(택배사 수신, 이 문제용): RCV_NO(회차) · ORD_SEQ · DLV_CO · RAW_ST · EVT_DT · 회차마다 평균 4,400행 · 인덱스 IX_DLV_RCV_NO (RCV_NO)T_DLV_TRACK(배송 추적, 이 문제용): 주문당 한 행 · PK_T_DLV_TRACK (ORD_SEQ) · DLV_CO · DLV_ST · LAST_EVT_DTPKG_DLV_MAP.TO_STD(dlv_co, raw_st): 택배사별 상태 코드를 표준 코드로 바꾸는 PL/SQL 함수(SQL 없음) · 고객센터 화면도 같은 함수를 쓴다PROCEDURE APPLY_DLV_STATUS(p_rcv_no NUMBER) IS
v_st VARCHAR2(10);
BEGIN
FOR r IN (SELECT ORD_SEQ, DLV_CO, RAW_ST, EVT_DT
FROM T_DLV_RCV
WHERE RCV_NO = p_rcv_no) LOOP
v_st := PKG_DLV_MAP.TO_STD(r.DLV_CO, r.RAW_ST);
UPDATE T_DLV_TRACK
SET DLV_ST = v_st, LAST_EVT_DT = r.EVT_DT
WHERE ORD_SEQ = r.ORD_SEQ;
IF SQL%ROWCOUNT = 0 THEN -- 처음 오는 주문
INSERT INTO T_DLV_TRACK (ORD_SEQ, DLV_CO, DLV_ST, LAST_EVT_DT)
VALUES (r.ORD_SEQ, r.DLV_CO, v_st, r.EVT_DT);
END IF;
END LOOP;
COMMIT;
END;
[AWR — 하루치 (SQL ordered by Executions)]
Executions Rows Processed CPU (s) SQL
475,236 437,412 31.2 UPDATE T_DLV_TRACK SET DLV_ST = :B3 , LAST_EVT_DT = :B2 WHERE ORD_SEQ = :B1
37,824 37,824 4.9 INSERT INTO T_DLV_TRACK (ORD_SEQ, DLV_CO, DLV_ST, LAST_EVT_DT) VALUES (:B4 , …)
108 475,236 0.4 SELECT ORD_SEQ, DLV_CO, RAW_ST, EVT_DT FROM T_DLV_RCV WHERE RCV_NO = :B1
[한 회차 — 4,400행 (V$MYSTAT 증가분)]
경과 0.41 초 · CPU 0.38 초 · recursive calls 4,797 · execute count 4,752
session logical reads 20,614 · redo size 2.0 MB