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

정정 반영 버튼을 누를 때마다 주문 100만 건을 읽고, 반영되지 않은 정정이 가끔 '반영'으로 찍힌다

실전UPDATE한빛유통455 / 700

상황 ​

정산팀은 고객 응대 중 주문 금액 정정이 확정되면 정정 요청(T_ORD_FIX)에 넣고 「정정 반영」 버튼을 누른다. 버튼은 아래 두 문장을 실행하고 커밋한다. 하루 스무 번쯤 누르고 한 번에 30 ~ 60건이다. DBA 주간 보고에서 이 UPDATE가 논리 읽기 Top SQL 3위였고(하루 약 12만 블록), 개발팀은 T_ORD_BIG에 ORD_SEQ 유일 인덱스를 만들자고 한다. 그런데 지난주 정산팀 조민우가 다른 문제를 가져왔다. "정정 3건이 '반영'으로 찍혀 있는데 주문 금액은 그대로예요. 그날 반영 버튼을 누르는 동안 다른 직원이 정정을 넣었대요." 오과장은 인덱스를 더 만들면 일요일 재적재가 다시 느려지지 않느냐고 묻는다.

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 5,826블록 · PK와 유일 제약은 없지만 ORD_SEQ 값은 원천에서 유일하다 · ORD_DT는 DATE(전부 자정)
  • 인덱스는 IX_ORD_BIG_DT_AMT (ORD_DT, ORD_AMT)와 IX_ORD_BIG_DT_SEQ (ORD_DT, ORD_SEQ) 둘이다(높이 3). 일요일 밤 재적재는 TRUNCATE, 인덱스 UNUSABLE, APPEND 적재, REBUILD 순서다(교재 14화).
  • T_ORD_FIX(정정 요청, 이 문제를 위해 둔 테이블): PK (ORD_SEQ) · ORD_DT(정산 화면이 주문에서 그대로 옮겨 적는다) · NEW_AMT · APPLY_YN('N' 대기, 'Y' 반영) · RUN_ID(지금은 쓰지 않는 빈 칸) · 반영된 요청은 매일 밤 이력으로 옮기고 지운다(낮 동안 최대 800행, 5블록)
  • 정정 요청은 화면에서 한 건씩 INSERT하고 바로 커밋한다. 시퀀스는 새로 만들어도 된다.

원본 SQL ​

sql
-- 「정정 반영」 버튼 (정산 화면)
UPDATE (SELECT o.ORD_AMT, f.NEW_AMT
          FROM T_ORD_BIG o, T_ORD_FIX f
         WHERE o.ORD_SEQ = f.ORD_SEQ
           AND f.APPLY_YN = 'N')
   SET ORD_AMT = NEW_AMT;

UPDATE T_ORD_FIX SET APPLY_YN = 'Y' WHERE APPLY_YN = 'N';
COMMIT;

실행계획 학습용 예시 ​

xplan
[반영 한 번 — 대기 정정 45건]
-----------------------------------------------------------------------------------------
| Id  | Operation           | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT    |           |      1 |        |      0 |00:00:00.14 |    6101 |
|   1 |  UPDATE             | T_ORD_BIG |      1 |        |      0 |00:00:00.14 |    6101 |
|*  2 |   HASH JOIN         |           |      1 |     45 |     45 |00:00:00.13 |    5831 |
|*  3 |    TABLE ACCESS FULL| T_ORD_FIX |      1 |     45 |     45 |00:00:00.01 |       5 |
|   4 |    TABLE ACCESS FULL| T_ORD_BIG |      1 |   1000K|   1000K|00:00:00.09 |    5826 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("O"."ORD_SEQ"="F"."ORD_SEQ")
   3 - filter("F"."APPLY_YN"='N')

[하루] 반영 약 20번 · 이 UPDATE의 논리 읽기 약 122,000 (Top SQL 3위) · 고치는 행마다 IX_ORD_BIG_DT_AMT도 고친다

[지난주 화요일 14:20 — 반영 한 번 동안]
  14:20:03.1  ① 조인 뷰 UPDATE 시작 · 그 순간 커밋된 대기 정정 41건을 반영
  14:20:03.2  다른 직원이 정정 3건 INSERT · COMMIT
  14:20:03.3  ② APPLY_YN = 'Y' 44건 · COMMIT   → 3건은 금액이 그대로인데 '반영'

문제 ​

  1. 이 UPDATE가 T_ORD_BIG을 매번 다 읽는 이유를 실행계획으로 설명하고, 조인 뷰 UPDATE가 허용되는 근거를 쓰시오. 정정 3건이 반영되지 않고 '반영'으로 찍힌 이유도 설명하시오.
  2. (가) ORD_SEQ에 유일 인덱스를 새로 만든다, (나) 조인 조건에 ORD_DT를 더해 지금 있는 인덱스로 찾아가게 한다, (다) 정정을 모아 밤에 한 번 반영한다를 반영 한 번의 읽는 양, 재적재와 저장 공간에 주는 부담, 업무 요구로 비교하시오.
  3. 고른 방법으로 반영 처리를 다시 작성하시오. 다른 직원이 동시에 정정을 넣어도 실제로 반영한 정정만 '반영'으로 찍히게 하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자