Skip to content
튜닝 연습DML과 배치 튜닝
DML-056

주문상세 6만 행 야간 적재가 19초로 늘자 세 사람이 서로 다른 처방을 들고 왔다

실전PLSQL한빛유통481 / 700

상황 ​

한빛유통은 매일 01:00에 제휴몰 주문상세 약 6만 행을 대용량 주문상세 T_ORD_BIG_DET에 더한다. 이 단계가 19초로 늘어 01:00 ~ 01:30 창이 빠듯해졌다. 박팀장이 리허설 사본에서 대상 테이블의 인덱스, 제약, 트리거를 하나씩 더해 가며 6만 행 적재를 재게 했다(교재 14화 실습/01과 같은 방식). 세 사람이 처방을 들고 왔다. (가) 개발팀: "FK 검사 때문이니 FK를 지우죠." (나) DBA: "14화대로 인덱스를 끄고 APPEND로 넣은 뒤 다시 짓죠." (다) 오과장: "트리거를 지우고 수정 일시와 수정자는 적재 SELECT에서 채우죠."

테이블과 인덱스 ​

  • T_ORD_BIG_DET(문제 설정, T_ORD_BIG 주문의 상세): 2,000,000행 · 8,960블록 · ORD_SEQ · ORD_DET_NO · ORD_DT · ITM_ID · ORD_QTY · UNT_PRC · UPD_DT · UPD_USER. 매일 약 6만 행(3%)이 더해진다.
  • PK_T_OBD (ORD_SEQ, ORD_DET_NO) · IX_OBD_ITM (ITM_ID)(상품별 판매 화면, 하루 수백 번) · IX_OBD_DT (ORD_DT)(2023년 연간 리포트 때 만들었다)
  • FK_OBD_ITM (ITM_ID) → M_ITM · 행 트리거 TRG_OBD_UPD(BEFORE INSERT OR UPDATE, UPD_DT와 UPD_USER를 채운다)
  • 낮에는 고객센터 화면이 주문상세 수량을 정정한다(UPDATE, 하루 수백 건). 정정 추적에 UPD_DT와 UPD_USER를 쓴다. 주문 시스템도 낮에 한 건씩 INSERT한다.
  • 01:00 ~ 01:30에는 이 테이블에 쓰는 다른 세션이 없다. 운영은 ARCHIVELOG다.

원본 SQL ​

sql
-- 매일 01:00 · 제휴몰 주문상세 적재
PROCEDURE P_OBD_LOAD IS
BEGIN
  INSERT INTO T_ORD_BIG_DET (ORD_SEQ, ORD_DET_NO, ORD_DT, ITM_ID, ORD_QTY, UNT_PRC)
  SELECT ORD_SEQ, ORD_DET_NO, ORD_DT, ITM_ID, ORD_QTY, UNT_PRC
    FROM STG_OBD;
  COMMIT;
END;

-- 2019년부터 있는 트리거
CREATE OR REPLACE TRIGGER TRG_OBD_UPD
BEFORE INSERT OR UPDATE ON T_ORD_BIG_DET
FOR EACH ROW
BEGIN
  :NEW.UPD_DT   := SYSDATE;
  :NEW.UPD_USER := USER;
END;

실행계획 학습용 예시 · 부수비용 분해는 교재 14화 §1 · §2.1의 측정 방식과 비율 ​

xplan
[적재 청구서 — 리허설 사본 · 6만 행 · 하나씩 더해 가며 (ARCHIVELOG)]
  대상 테이블 상태                     redo       db block changes   session logical reads   경과
  아무것도 없음                         2.9 MB          2,410               3,380            0.2 초
  + PK_T_OBD                           17.4 MB        122,700             184,600            2.9 초
  + IX_OBD_ITM                         31.9 MB        243,100             365,200            6.8 초
  + IX_OBD_DT                          46.4 MB        363,400             545,900           11.2 초
  + FK_OBD_ITM                         46.4 MB        363,400             659,300           12.1 초
  + TRG_OBD_UPD (= 지금 운영)          58.8 MB        463,600             762,100           19.0 초

[(나)를 리허설 사본에서 해 본 결과]
  ALTER INDEX PK_T_OBD UNUSABLE 뒤 INSERT       → ORA-01502: index 'SQLP.PK_T_OBD' … is in unusable state
  트리거와 FK가 켜진 채 /*+ APPEND */            → LOAD TABLE CONVENTIONAL (Note: Direct Load disabled because triggers are defined)
  일반 인덱스 둘만 끄고 넣은 뒤 REBUILD          → 적재 9.8 초 + REBUILD 둘(200만 행 정렬) 21.4 초 = 31.2 초

[DBA_INDEX_USAGE · 최근 90일]
  PK_T_OBD 1,204,330 · IX_OBD_ITM 41,380 · IX_OBD_DT 0

[FK_OBD_ITM이 막은 적재 오류 — 지난 1년]
  3번 (제휴몰이 단종 상품 코드를 보냄 · ORA-02291로 적재 실패 → 제휴몰에 반송)

문제 ​

  1. 적재 청구서를 읽고 19초와 redo 58.8MB가 무엇에서 얼마씩 나오는지 정리하시오.
  2. 세 처방 (가), (나), (다)를 각각 숫자와 부작용으로 평가하시오.
  3. 최종안을 SQL로 작성하고, 고친 뒤의 redo와 경과를 어림하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자