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

보정 누락분을 한 번에 넣은 7분 동안 보정 화면 11개가 멈춰 있었다

기초INSERT한빛유통459 / 700

상황 ​

월요일 10:24, 정산팀 조민우가 지난주 보정에서 빠진 정산 1,240건을 SQL Developer로 한 번에 넣었다. 교재에서 본 대로 /*+ APPEND */를 붙였고 문장은 0.06초 만에 끝났다. 넣은 건수와 금액을 맞춰 본 뒤 10:31에 커밋했다. 그 7분 동안 보정 화면을 쓰던 정산팀 11명의 저장 버튼이 돌기만 했다. 화면 담당자: "보정 한 건 저장은 늘 0.01초인데, 그 시간에만 전부 멈췄어요."

테이블과 인덱스 ​

  • T_STLM_ADJ 보정 이력(교재 15화): 98,780행 · 약 420블록 · PK_T_STLM_ADJ (STLM_SEQ) · 낮에는 보정 화면이 한 건씩 INSERT하거나 UPDATE한다(시간당 약 300건).
  • T_ORD_STLM 정산: 100,020행 · 640블록 · 인덱스 없음 · 금액 미확정(STLM_AMT NULL) 20건
  • M_CUS 고객: 2,000행 · 30블록 · PK_M_CUS (CUS_ID)
  • 보정률은 등급 A 0.1%, B 0.2%, 그 밖 0.3%다. SQL Developer는 자동 커밋을 끄고 쓴다.

원본 SQL ​

sql
-- 10:24 · SQL Developer · 지난주 보정 누락분
INSERT /*+ APPEND */ INTO T_STLM_ADJ (STLM_SEQ, ADJ_RATE, ADJ_AMT, ADJ_DT)
SELECT s.STLM_SEQ, r.ADJ_RATE, ROUND(s.STLM_AMT * r.ADJ_RATE), SYSDATE
  FROM T_ORD_STLM s
  JOIN (SELECT CUS_ID,
               CASE CUS_GD WHEN 'A' THEN 0.001 WHEN 'B' THEN 0.002 ELSE 0.003 END AS ADJ_RATE
          FROM M_CUS) r
    ON r.CUS_ID = s.CUS_ID
 WHERE s.STLM_AMT IS NOT NULL
   AND NOT EXISTS (SELECT 1 FROM T_STLM_ADJ a WHERE a.STLM_SEQ = s.STLM_SEQ);

-- (건수와 금액을 이것저것 맞춰 본 뒤) 10:31
COMMIT;

실행계획 학습용 예시 ​

xplan
[10:24:48 · SID 147 (SQL Developer) — 1,240 rows inserted]
-----------------------------------------------------------------------------------------------------
| Id  | Operation               | Name          | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT        |               |      1 |        |      0 |00:00:00.06 |     981 |
|   1 |  LOAD AS SELECT         | T_STLM_ADJ    |      1 |        |      0 |00:00:00.06 |     981 |
|*  2 |   HASH JOIN             |               |      1 |   1240 |   1240 |00:00:00.03 |     906 |
|   3 |    TABLE ACCESS FULL    | M_CUS         |      1 |   2000 |   2000 |00:00:00.01 |      30 |
|*  4 |    HASH JOIN ANTI       |               |      1 |   1240 |   1240 |00:00:00.03 |     876 |
|*  5 |     TABLE ACCESS FULL   | T_ORD_STLM    |      1 |    100K|    100K|00:00:00.01 |     640 |
|   6 |     INDEX FAST FULL SCAN| PK_T_STLM_ADJ |      1 |  98780 |  98780 |00:00:00.01 |     236 |
-----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("CUS_ID"="S"."CUS_ID")
   4 - access("A"."STLM_SEQ"="S"."STLM_SEQ")
   5 - filter("S"."STLM_AMT" IS NOT NULL)

[10:31:00 · V$LOCK — T_STLM_ADJ 관련]
   SID  프로그램         TYPE  LMODE  REQUEST  CTIME(초)  BLOCK
   147  SQL Developer    TM      6        0       372       1
   147  SQL Developer    TX      6        0       372       0
   203  보정 화면        TM      0        3       351       0
   219  보정 화면        TM      0        3       298       0
   …    (보정 화면 세션 11개가 같은 모양)

[ASH · 10:24 ~ 10:31 · 보정 화면 세션]
   enq: TM - contention   96% · blocking_session = 147

문제 ​

  1. 보정 화면 11개가 7분 동안 멈춘 원인을 V$LOCK의 숫자로 설명하시오.
  2. 같은 누락분을 넣는 방법을 다시 작성하고, 낮에 이 테이블에 넣을 때 무엇을 지켜야 하는지 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자