테마
이 문제는 교재 18화 졸업 과제와 같은 이커머스 데이터베이스를 씁니다. 『튜너의 1년』을 순서대로 읽고 있다면 졸업 과제를 먼저 풀고 오세요. 아래 「테이블과 인덱스」 칸에 과제의 답 일부(제약 조건, 인덱스, 통계의 실제 상태)가 나옵니다.
CRM팀의 「월말 포인트 명세」는 고객 5,230명 전부의 포인트 거래 합계를 한 장으로 뽑는다. 담당자가 물었다. "실행계획을 떠 보면 51블록이에요. 그런데 9초가 걸려요. 서버가 작아서 그런가요?"
합계는 개발팀이 만든 함수 fn_point_sum이 고객마다 구한다.
customers: 5,230행 · 51블록 · PK(customer_id)point_transactions: 45,000행 · 210블록 · PK(tx_id)만 있다 · customer_id 인덱스 없음 · 고객 한 명에 평균 약 9건 · 거래가 없는 고객이 있을 수 있다dep=1).CREATE OR REPLACE FUNCTION fn_point_sum(p_cust NUMBER) RETURN NUMBER IS
v_sum NUMBER;
BEGIN
SELECT NVL(SUM(amount), 0) INTO v_sum
FROM point_transactions
WHERE customer_id = p_cust;
RETURN v_sum;
END;
/
SELECT c.customer_id, c.name, c.grade,
fn_point_sum(c.customer_id) AS point_sum
FROM customers c
ORDER BY c.customer_id;
[바깥 문장 — DISPLAY_CURSOR (ALLSTATS LAST)]
------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 5230 |00:00:09.12 | 51 | |
| 1 | SORT ORDER BY | | 1 | 5230 | 5230 |00:00:09.12 | 51 | 372K (0)|
| 2 | TABLE ACCESS FULL| CUSTOMERS | 1 | 5230 | 5230 |00:00:00.01 | 51 | |
------------------------------------------------------------------------------------------------------
[세션 통계 — 이 문장 한 번 (V$MYSTAT 증가분)]
경과 시간 9.1 초 (거의 전부 CPU)
recursive calls 5,236
execute count 5,232
session logical reads 1,098,412
[V$SQL — 함수 안의 문장 (dep=1)]
SQL_TEXT EXECUTIONS FETCHES ROWS_PROCESSED BUFFER_GETS
SELECT NVL(SUM(AMOUNT), 0) FROM POINT_TRANSACTIONS WHERE CUSTOMER_ID = :B1 5,230 5,230 5,230 1,098,300
계획 : SORT AGGREGATE ← TABLE ACCESS FULL POINT_TRANSACTIONS · filter("CUSTOMER_ID"=:B1) · 한 번 210 블록
V$SQL로 설명하시오.