Skip to content
튜닝 연습Lock과 동시성 제어
LOCK-050

오후 3시에 돌린 2022년 주문 정리 3분 동안 반품 접수는 멈추고 대사 리포트는 서른 배 느려졌다

실전UPDATE한빛유통545 / 700

상황 ​

한빛유통 고객센터의 요청으로 2022년 완료 주문을 「보관」 상태로 바꿔 화면의 기본 목록에서 빼기로 했다. 개발팀은 목요일 15:00에 UPDATE 한 문장으로 돌렸고 2분 52초 만에 끝났다. 그 3분 동안 고객센터의 「반품 접수」 세 건이 길게는 2분 50초 멈췄고, 정산팀의 「연간 대사 리포트」가 평소 0.4초에서 12초로 늘었다. 신규 주문은 멀쩡했다. 다음 달에는 2023년 상반기 주문을 정리할 예정이라 오과장이 방법을 비교해 달라고 했다.

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 5,826블록 · 이 문제에서는 운영 주문 테이블 역할을 한다 · ORD_DT 2022-01-01 ~ 2024-12-31(날짜순 적재) · 2022년 주문은 333,000행 남짓이고 그중 COMPLETE가 90%
  • 인덱스: UX_ORD_BIG_SEQ (ORD_SEQ) UNIQUE · IX_ORD_BIG_CUS (CUS_ID, ORD_DT) · ORD_DT와 ORD_ST에는 인덱스가 없다
  • 고객센터 「반품 접수」는 ORD_SEQ로 주문 한 건의 ORD_ST를 RETURN으로 바꾼다(하루 수백 건, 오래된 주문도 온다)
  • 「연간 대사 리포트」는 T_ORD_BIG을 통째로 읽어 연도와 상태별로 센다(시간당 수십 번)
  • T_JOB_LOG 작업 기록(문제 설정): 작업 이름, 조각, 바꾼 행 수, 끝난 시각 · 언두 테이블스페이스는 넉넉하다

원본 SQL ​

sql
-- 목요일 15:00 · 한 문장 · 끝에 COMMIT
UPDATE T_ORD_BIG
   SET ORD_ST = 'ARCHIVE'
 WHERE ORD_DT < DATE '2023-01-01'
   AND ORD_ST = 'COMPLETE';
COMMIT;

실행계획 학습용 예시 · CR 블록이 만들어지는 과정은 교재 13화 §4.5 ​

xplan
[UPDATE — ALLSTATS LAST · 15:00:04 ~ 15:02:56 (SID 201)]
----------------------------------------------------------------------------------------
| Id  | Operation          | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |           |      1 |        |      0 |00:02:52.10 |    312K |
|   1 |  UPDATE            | T_ORD_BIG |      1 |        |      0 |00:02:52.10 |    312K |
|*  2 |   TABLE ACCESS FULL| T_ORD_BIG |      1 |    300K|    299K|00:00:01.30 |    5826 |
----------------------------------------------------------------------------------------
   2 - filter(("ORD_DT"<TO_DATE(' 2023-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "ORD_ST"='COMPLETE'))
  세션 통계: redo size 81 MB · undo change vector size 74 MB · 고친 행 299,412

[반품 접수 — 15:01:20 의 V$SESSION]
SID   EVENT                            SECS   BLOCKING_SESSION   하는 문장
118   enq: TX - row lock contention      74   201                UPDATE T_ORD_BIG SET ORD_ST = 'RETURN' WHERE ORD_SEQ = :B1   (2022-01 주문)
133   enq: TX - row lock contention      31   201                (2022-04 주문)
(15:02:10 에 온 2022-06 주문의 반품은 46초 기다림 · 같은 3분 동안 2024년 주문의 반품 6건은 0.01초)

[연간 대사 리포트 — 평소 (ALLSTATS LAST)]
----------------------------------------------------------------------------------------
| Id  | Operation          | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |      1 |        |      9 |00:00:00.41 |    5826 |
|   1 |  HASH GROUP BY     |           |      1 |      9 |      9 |00:00:00.41 |    5826 |
|   2 |   TABLE ACCESS FULL| T_ORD_BIG |      1 |   1000K|   1000K|00:00:00.18 |    5826 |
----------------------------------------------------------------------------------------
[같은 리포트 — 15:02:30 에 시작한 한 번]
|   0 | SELECT STATEMENT   |           |      1 |        |      9 |00:00:12.07 |    260K |
|   1 |  HASH GROUP BY     |           |      1 |      9 |      9 |00:00:12.07 |    260K |
|   2 |   TABLE ACCESS FULL| T_ORD_BIG |      1 |   1000K|   1000K|00:00:11.85 |    260K |
  세션 통계: consistent gets 260,140 · data blocks consistent reads - undo records applied 252,600 · 기다린 enqueue 0

문제 ​

  1. 같은 3분 동안 반품 접수와 연간 대사 리포트, 신규 주문이 각각 무엇을 겪었는지 실행계획과 V$SESSION, 세션 통계를 근거로 구분해 설명하시오.
  2. 다음 달 2023년 상반기 정리에 쓸 방법을 셋 이상 비교하고 하나를 골라 SQL로 쓰시오. 고른 방법의 부작용과 그 대비도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자