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

상품평가 한 건 등록에 SQL이 두 번 오가고, 신상품 출시 시각에는 평가 등록이 ORA-00001로 실패한다

실전PLSQL한빛유통456 / 700

상황 ​

고객이 상품평가를 등록하면 화면은 평가(T_ITM_EVL)를 넣은 뒤 상품별 평가 요약(T_ITM_EVL_SUM)을 고치는 프로시저 ADD_EVL_SUM을 부르고, 둘을 한 번에 커밋한다. 평가는 하루 1만 건쯤 들어온다. 지난 화요일 10:00에 신상품 8개를 출시했는데, 10:00 ~ 10:02 사이에 평가 등록 3건이 ORA-00001로 실패해 고객 화면에 '등록 실패'가 떴다. 개발팀은 MERGE로 바꾸면 해결된다고 한다. 박팀장은 방법별 비교와 근거를 요청했다.

테이블과 인덱스 ​

  • T_ITM_EVL 상품평가: 5,000행 · 48블록 · PK_T_ITM_EVL (ITM_ID, EVL_LST_NO)
  • T_ITM_EVL_SUM(상품별 평가 요약, 이 문제를 위해 둔 테이블): 상품 100개 + 신상품 8개 · PK (ITM_ID) · EVL_CNT, EVL_PT_SUM, LAST_EVL_DT · 상품의 첫 평가가 들어올 때 행이 생긴다
  • M_ITM 상품: 100행(출시 뒤 108행) · PK_M_ITM
  • 하루 평가 1만 건 가운데 상품의 첫 평가는 그날 출시한 상품 수만큼이다(지난 화요일 8건).

원본 SQL ​

sql
PROCEDURE ADD_EVL_SUM(p_itm VARCHAR2, p_pt NUMBER) IS
  v_cnt NUMBER;
BEGIN
  SELECT COUNT(*) INTO v_cnt
    FROM T_ITM_EVL_SUM
   WHERE ITM_ID = p_itm;                         -- 요약 행이 있나
  IF v_cnt = 0 THEN
    INSERT INTO T_ITM_EVL_SUM (ITM_ID, EVL_CNT, EVL_PT_SUM, LAST_EVL_DT)
    VALUES (p_itm, 1, p_pt, SYSDATE);
  ELSE
    UPDATE T_ITM_EVL_SUM
       SET EVL_CNT = EVL_CNT + 1, EVL_PT_SUM = EVL_PT_SUM + p_pt, LAST_EVL_DT = SYSDATE
     WHERE ITM_ID = p_itm;
  END IF;
END;

실행계획 학습용 예시 ​

xplan
[TKPROF 요약 — 지난 화요일 평가 10,000건 (학습용 예시)]
  SQL                                                          Execute     Rows    query  current
  SELECT COUNT(*) FROM T_ITM_EVL_SUM WHERE ITM_ID = :B1         10,000   10,000   10,000        0
  UPDATE T_ITM_EVL_SUM SET EVL_CNT = EVL_CNT + 1, …              9,989    9,989    9,989   10,312
  INSERT INTO T_ITM_EVL_SUM (…) VALUES (…)                          11        8       14       57
  합계  SQL 실행 20,000 · 논리 읽기 약 40,400 · redo 약 3.1 MB

[오류 로그 — 10:00:07 ~ 10:01:52]
  ORA-00001: unique constraint (SQLP.PK_T_ITM_EVL_SUM) violated   3건
    신상품 3개에서, 같은 상품의 첫 평가가 두 세션에서 거의 동시에 들어왔다
  평가 등록 화면 '등록 실패' 3건 (평가 INSERT까지 함께 롤백)

문제 ​

  1. 지금 프로시저가 평가 한 건마다 하는 일과, 신상품 출시 시각에 ORA-00001이 난 이유를 설명하시오.
  2. (가) UPDATE를 먼저 하고 0건이면 INSERT, (나) INSERT를 먼저 하고 중복이면 UPDATE, (다) MERGE … USING DUAL을 SQL 실행 횟수, 읽는 양과 redo, 동시 등록에서의 안전성으로 비교하시오.
  3. 고른 방법으로 프로시저를 다시 작성하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자