Skip to content
튜닝 연습PL/SQL과 사용자 정의 함수
PLSQL-013

AWR 실행 횟수 1위가 소스 어디에도 없는 상품명 조회다

실전PLSQL버거663 / 700

상황 ​

버거 본사 DBA가 하루치 AWR을 보내왔다. 실행 횟수 1위는 SELECT ITEM_NM FROM ITEM WHERE ITEM_ID = :B1으로 하루 422만 번 실행되는데, 개발팀은 "그런 SQL은 소스에 없다"라고 한다. 개발팀장은 두 안을 놓고 고민 중이다. "상품명 함수에 RESULT_CACHE 한 단어를 붙이면 하루 만에 끝난다"는 안과, "함수를 부르는 프로그램 31개를 조인으로 고친다"는 안이다. 튜너에게 어느 쪽으로 갈지, 무엇을 잃는지 숫자로 정해 달라고 했다.

테이블과 인덱스 ​

  • ITEM 상품: 92행 · 5블록 · PK(ITEM_ID) · 분기마다 메뉴를 개편할 때만 바뀐다
  • ORD_ITEM 주문상품: 2,472,717행 · 55,265블록 · ORD_ITEM_PK (ORD_NO, ITEM_ID) · ORD_ITEM_X01 (ORD_DT, ORD_HMS) · 한 달에 약 103,000행
  • ORD 주문: 1,000,000행 · 22,422블록 · ORD_PK (ORD_NO) · ORD_X01 (ORD_DT, ORD_HMS)
  • 함수 FN_ITEM_NM: USER_DEPENDENCIES로 보면 31개 프로그램이 부른다 · 결과 캐시 1,984칸 · result_cache_mode = MANUAL
  • 아래 세 프로그램이 하루 호출의 99%를 차지한다(V$SQL에서 문장마다 실행 수와 행 수로 셈)

원본 SQL ​

sql
CREATE OR REPLACE FUNCTION FN_ITEM_NM(p_item_id NUMBER) RETURN VARCHAR2 IS
  v_nm ITEM.ITEM_NM%TYPE;
BEGIN
  SELECT ITEM_NM INTO v_nm FROM ITEM WHERE ITEM_ID = p_item_id;
  RETURN v_nm;
END;
/

-- [A] 매장 관리자 「영수증 다시 보기」: 주문 한 건의 상품 (실행 한 번에 평균 2.5행 · 하루 46,000번)
SELECT i.ITEM_ID, FN_ITEM_NM(i.ITEM_ID) AS item_nm, i.ORD_ITEM_QTY
  FROM ORD_ITEM i
 WHERE i.ORD_NO = :ord_no;

-- [B] 본사 「매장별 월간 판매 상품」 화면: 매장 하나, 한 달 (실행 한 번에 평균 515행 · 하루 2,300번)
SELECT o.ORD_NO, o.ORD_DT, i.ITEM_ID, FN_ITEM_NM(i.ITEM_ID) AS item_nm, i.ORD_ITEM_QTY
  FROM ORD o, ORD_ITEM i
 WHERE o.SHOP_NO = :shop_no
   AND o.ORD_DT BETWEEN :fr AND :to
   AND i.ORD_NO = o.ORD_NO;

-- [C] 본사 「상품 판매 내역 내려받기」: 한 달 치 주문상품 (실행 한 번에 평균 103,021행 · 하루 28번)
SELECT i.ORD_NO, i.ORD_DT, i.ORD_HMS, i.ITEM_ID, FN_ITEM_NM(i.ITEM_ID) AS item_nm, i.ORD_ITEM_QTY
  FROM ORD_ITEM i
 WHERE i.ORD_DT BETWEEN :fr AND :to;

실행계획 학습용 예시 ​

xplan
[AWR 하루: SQL ordered by Executions (1위)]
  Executions   Rows Processed   Buffer Gets   CPU (s)   Elapsed (s)   SQL Text
   4,225,812        4,225,812     8,451,624      71.3          88.6   SELECT ITEM_NM FROM ITEM WHERE ITEM_ID = :B1
  (Parse Calls 63 · 이 문장의 PROGRAM_ID → DEV.FN_ITEM_NM)

[V$SQL: FN_ITEM_NM을 부르는 문장 · 하루 증가분]
  프로그램                  실행 수   행 수(= 함수 호출)    비중
  [C] 내려받기                   28          2,884,588     68%
  [B] 매장별 화면             2,300          1,184,500     28%
  [A] 영수증 다시 보기       46,000            115,000      3%
  그 밖 28개 프로그램             …             41,724      1%

[복사본에서 잰 판: [C] 한 번 (103,021행)]
  판                          함수 본문    함수 호출   논리 읽기    경과
  그대로                        103,021      103,021     209,019   1.18 초
  스칼라 서브쿼리로 감싸기       10,163       10,163      23,303   0.16 초
  RESULT_CACHE (데운 뒤)              0      103,021       2,977   0.19 초
  ITEM과 조인                         0            0       2,982   0.07 초

[복사본에서 잰 판: [A] 한 번 (2.5행)]
  그대로 논리 읽기 10 · 스칼라 서브쿼리 10 (실행마다 캐시가 새로 시작) · RESULT_CACHE 5 · ITEM과 조인 10

문제 ​

  1. AWR 1위 문장이 소스에 없는 이유와, 그 문장을 누가 부르는지 찾는 방법을 설명하시오.
  2. 두 안(함수에 RESULT_CACHE, 프로그램 31개를 조인으로)을 숫자로 견주어 무엇을 언제 할지 정하고, 필요한 SQL을 쓰시오.
  3. 고른 안의 대가와, 결과 캐시를 붙여도 되는 근거를 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자