Skip to content
튜닝 연습파티션
PART-040

월 확정 재적재가 도는 3분 동안 정산 화면의 6월 매출이 0원으로 나온다

중급INSERT한빛유통415 / 700

상황 ​

한빛유통 정산팀은 매월 3일 10:00에 「월 확정 재적재」를 돌린다. 정산계가 정정을 모두 반영해 확정한 지난달 주문을 DB 링크로 받아, 주문 파티션 테이블의 그 달 칸을 통째로 다시 채운다. 같은 시각 정산팀 20명이 「월 매출」 화면으로 확정 금액을 맞춰 본다. 재적재가 도는 3분 남짓 동안 화면의 6월 매출은 0원으로 나온다. 7월 3일에는 10:02에 DB 링크가 끊겨 INSERT가 실패했고, 6월 매출은 다시 돌린 11:20까지 0원이었다. 박팀장: "도는 동안에도, 실패해도 화면에는 6월 숫자가 남아 있게 바꿔 줘."

테이블과 인덱스 ​

  • T_ORD_BIG_P14 주문(파티션 복사본, 교재 14화): 1,000,000행 · PARTITION BY RANGE (ORD_DT) 월별 36칸(P202201 ~ P202412)과 빈 PMAX, 모두 37칸. P202406은 30번째 칸이고 27,390행, FULL로 약 161블록이다.
  • 컬럼은 ORD_SEQ · CUS_ID · ORD_DT · ORD_ST · ORD_AMT다. LOCAL 인덱스 IX_P14_DT_AMT (ORD_DT, ORD_AMT) · IX_P14_CUS_DT (CUS_ID, ORD_DT)가 있고, 제약, GLOBAL 인덱스, 트리거는 없다.
  • T_ORD_FIX@STLM 확정 주문(정산계 테이블, DB 링크): 그 달 주문 전체를 정정까지 반영해 담는다. 6월분은 27,390행이고, 링크로 다 받는 데 약 3분이 걸린다.
  • 「월 매출」 화면은 ORD_DT 범위로 그 달 칸 하나만 읽는다. 재적재 시각에 이 테이블을 고치는 다른 작업은 없다. 운영은 ARCHIVELOG다.

원본 SQL ​

sql
-- 매월 3일 10:00 · 지난달 확정 재적재 (7월 3일 = 6월분)
ALTER TABLE T_ORD_BIG_P14 TRUNCATE PARTITION P202406;

INSERT INTO T_ORD_BIG_P14 (ORD_SEQ, CUS_ID, ORD_DT, ORD_ST, ORD_AMT)
SELECT ORD_SEQ, CUS_ID, ORD_DT, ORD_ST, ORD_AMT
  FROM T_ORD_FIX@STLM
 WHERE ORD_DT >= DATE '2024-06-01'
   AND ORD_DT <  DATE '2024-07-01';
COMMIT;

-- 「월 매출」 화면
SELECT COUNT(*), SUM(ORD_AMT)
  FROM T_ORD_BIG_P14
 WHERE ORD_DT >= :v_from
   AND ORD_DT <  :v_to;

실행계획 학습용 예시 · 교재 14화 규모 ​

xplan
[배치 로그 · 7월 3일]
  10:00:01  ALTER TABLE T_ORD_BIG_P14 TRUNCATE PARTITION P202406    0.3초 (DDL · 문장 앞뒤로 커밋)
  10:00:02  INSERT INTO T_ORD_BIG_P14 ... FROM T_ORD_FIX@STLM       시작
  10:02:14  ORA-02068: following severe error from STLM              INSERT 롤백
  11:20:05  (수동) TRUNCATE + INSERT 다시 실행                        3분 08초 · 27,390행

[INSERT · 6월 3일의 정상 실행]
-------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name          | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
-------------------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT             |               |      1 |        |      0 | 00:03:07.92 |   83118 |        |       |
|   1 |  LOAD TABLE CONVENTIONAL     | T_ORD_BIG_P14 |      1 |        |      0 | 00:03:07.92 |   83118 |        |       |
|   2 |   REMOTE                     | T_ORD_FIX     |      1 |  27390 |  27390 | 00:03:04.10 |       0 |        |       |
-------------------------------------------------------------------------------------------------------------------------

Remote SQL Information (identified by operation id):
----------------------------------------------------
   2 - SELECT "ORD_SEQ","CUS_ID","ORD_DT","ORD_ST","ORD_AMT" FROM "T_ORD_FIX" "T_ORD_FIX"
       WHERE "ORD_DT">=TO_DATE(' 2024-06-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
       "ORD_DT"<TO_DATE(' 2024-07-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') (accessing 'STLM')

  세션 통계 (TRUNCATE + INSERT + COMMIT): redo size 약 11.8 MB · undo change vector size 약 3.9 MB

[「월 매출」 화면 · 10:01 재적재 중 · :v_from = 2024-06-01, :v_to = 2024-07-01]
-------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name          | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
-------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |               |      1 |        |      1 | 00:00:00.01 |       3 |        |       |
|   1 |  SORT AGGREGATE              |               |      1 |      1 |      1 | 00:00:00.01 |       3 |        |       |
|*  2 |   FILTER                     |               |      1 |        |      0 | 00:00:00.01 |       3 |        |       |
|   3 |    PARTITION RANGE ITERATOR  |               |      1 |  27390 |      0 | 00:00:00.01 |       3 |    KEY |   KEY |
|*  4 |     TABLE ACCESS FULL        | T_ORD_BIG_P14 |      1 |  27390 |      0 | 00:00:00.01 |       3 |    KEY |   KEY |
-------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(:V_FROM<:V_TO)
   4 - filter(("ORD_DT">=:V_FROM AND "ORD_DT"<:V_TO))

  (실행 때 고른 칸: 30번 P202406 · 평소에는 A-Rows 27,390 · Buffers 161)

문제 ​

  1. 재적재가 도는 3분 동안 화면이 6월을 0원으로 본 까닭과, 실패한 날 0원이 한 시간 넘게 남은 까닭을 TRUNCATE와 INSERT의 트랜잭션 경계로 설명하시오.
  2. 재적재가 도는 동안에도, 실패해도 화면에 6월 숫자가 남도록 파티션 교환(EXCHANGE)으로 배치를 다시 작성하시오.
  3. 교환 방식의 대가와 교환하기 전에 확인할 것을 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자