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

점심 피크마다 POS 결제 저장이 몇 초씩 멈추는데, 기다리는 상대가 같은 버거를 판 다른 매장이다

실전PLSQL버거480 / 700

상황 ​

버거원 본사의 「실시간 메뉴 판매판」은 전 매장의 오늘 상품별 판매 수량을 보여 준다. 2년 전 ORD_ITEM에 행 트리거를 달아, 주문상품이 들어올 때마다 합계 테이블 ITEM_DAY_QTY의 그 상품 행에 수량을 더하게 했다. 이 문제에서 POS는 첫 상품을 찍을 때부터 ORD와 ORD_ITEM에 넣기 시작해 결제가 끝나면 COMMIT한다(보통 20 ~ 40초). 점심 피크(11:30 ~ 13:30)에 결제 저장이 몇 초씩 멈춘다는 매장 문의가 늘었고, 월말에 POS 업체가 하루치를 다시 보내 오면 그 적재도 느리다. 개발팀은 두 안을 냈다. (가) 트리거 본문을 자율 트랜잭션으로 바꿔 합계를 바로 COMMIT한다. (나) 복합 트리거(COMPOUND TRIGGER)로 바꿔 문장이 끝날 때 상품별로 모아 한 번에 더한다.

테이블과 인덱스 ​

  • ORD_ITEM 주문상품: 2,472,717행 · 55,265블록 · 하루 약 3,400행 · ORD_ITEM_PK (ORD_NO, ITEM_ID) · ORD_ITEM_X01 (ORD_DT, ORD_HMS)
  • ITEM 상품: 92행 · 인기 상품 상위 5개가 판매 수량의 절반이다.
  • ITEM_DAY_QTY 합계(문제 설정): ORD_DT · ITEM_ID · QTY · PK (ORD_DT, ITEM_ID) · 하루 92행 이하
  • 판매판은 본사 화면 8개가 1분마다 새로 고친다. MD팀은 "1분쯤 늦는 것은 괜찮다"고 확인했다.
  • 매장 200곳 · 계산대 약 450대. 03:00 배치 창에는 POS 입력이 없다.

원본 SQL ​

sql
-- 2년 전 · 판매판 합계 트리거
CREATE OR REPLACE TRIGGER TRG_ORD_ITEM_QTY
AFTER INSERT ON ORD_ITEM
FOR EACH ROW
BEGIN
  MERGE INTO ITEM_DAY_QTY q
  USING (SELECT :NEW.ORD_DT AS ORD_DT, :NEW.ITEM_ID AS ITEM_ID FROM DUAL) s
     ON (q.ORD_DT = s.ORD_DT AND q.ITEM_ID = s.ITEM_ID)
   WHEN MATCHED THEN UPDATE SET q.QTY = q.QTY + :NEW.ORD_ITEM_QTY
   WHEN NOT MATCHED THEN INSERT (ORD_DT, ITEM_ID, QTY)
        VALUES (s.ORD_DT, s.ITEM_ID, :NEW.ORD_ITEM_QTY);
END;

-- 판매판 (1분마다)
SELECT ITEM_ID, QTY
  FROM ITEM_DAY_QTY
 WHERE ORD_DT = TO_CHAR(SYSDATE, 'YYYYMMDD');

실행계획 학습용 예시 · 판매판 새 SQL의 Buffers는 교재 14화 규모(하루 약 3,400행) ​

xplan
[ASH — 점심 피크 · POS 세션의 대기]
  EVENT                             비율    대상
  enq: TX - row lock contention      61%    ITEM_DAY_QTY 의 상위 5개 상품 행 (I001 빅버거 세트 · I014 콜라 …)
  CPU · log file sync 등             39%
  POS 결제 저장 시간                 평소 0.05 초 · 피크 p95 2.4 초 · 최대 31 초

[V$SESSION — 12:14:05 표본]
  SID   PROGRAM      EVENT                            SECS   BLOCKING_SESSION   하고 있는 문장
  412   POS_0071_1   enq: TX - row lock contention       3   388                MERGE INTO ITEM_DAY_QTY …
  388   POS_0133_2   SQL*Net message from client        24                      (손님이 결제 중 · 트랜잭션을 연 채)

[월말 재전송 — 하루치 3,418행 다시 넣기 · TKPROF]
  INSERT INTO ORD_ITEM … SELECT … FROM STG_ORD_ITEM      Execute 1       rows 3,418
  MERGE INTO ITEM_DAY_QTY … (트리거 안)                  Execute 3,418
  경과 1.9 초 (트리거를 끈 시험 DB 0.2 초)

[판매판 — 지금] ITEM_DAY_QTY 에서 읽기 · Buffers 3

문제 ​

  1. 점심 피크의 POS 대기와 재전송 적재의 1.9초가 각각 트리거의 어떤 성질에서 나오는지 설명하시오.
  2. 개발팀의 (가)와 (나)를 평가하고, 판매판을 유지하는 방법을 SQL로 작성하시오.
  3. 고친 방법의 대가와, 운영에서 바꿀 때의 순서를 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자