테마
버거 본사 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 = MANUALV$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;
[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
RESULT_CACHE, 프로그램 31개를 조인으로)을 숫자로 견주어 무엇을 언제 할지 정하고, 필요한 SQL을 쓰시오.