테마
이 문제는 교재 18화 졸업 과제와 같은 이커머스 데이터베이스를 씁니다. 『튜너의 1년』을 순서대로 읽고 있다면 졸업 과제를 먼저 풀고 오세요. 아래 「테이블과 인덱스」 칸에 과제의 답 일부(제약 조건, 인덱스, 통계의 실제 상태)가 나옵니다.
이커머스의 「카테고리 상품 목록」 API는 MySQL 시절의 프로시저를 옮겨 온 것이다. 요청마다 고른 카테고리의 하위 카테고리를 임시 테이블로 만들고, 상품과 조인한 뒤 그 테이블을 지운다. 세일 기간에는 초당 40번쯤 호출된다. 같은 기간 고객센터에는 "결제는 안 했는데 주문서가 남아 있다"는 문의가 하루 몇 건씩 들어온다. 주문 화면은 주문을 저장하는 도중에 프로모션 대상인지 확인하려고 같은 로직을 부른다.
categories: 53행 · 4블록 · parent_id로 이어진 계층 · PK(category_id)만 있다products: 280행 · 8블록 · PK(product_id)만 있다 · 상품은 카테고리마다 5개 남짓orders: 34,908행 · 193블록 · 주문 화면은 orders에 한 행을 넣은 뒤 결제가 끝나면 커밋하고, 실패하면 ROLLBACK한다.CURSOR_SHARING = EXACT-- 요청 하나 (요청 번호 48213 · 카테고리 12)
CREATE TABLE TMP_CAT_48213 AS
SELECT category_id
FROM categories
START WITH category_id = 12
CONNECT BY PRIOR category_id = parent_id;
SELECT p.product_id, p.name
FROM products p, TMP_CAT_48213 t
WHERE p.category_id = t.category_id
ORDER BY p.name;
DROP TABLE TMP_CAT_48213 PURGE;
[AWR · 세일 첫날 20:00 ~ 21:00 · Load Profile (초당)]
DB CPU 1.9
Executes (SQL) 1,540
Parses (SQL) 402
Hard parses (SQL) 131
Redo size (bytes) 1,184,000
[Top Foreground Events]
이벤트 % DB time
row cache lock 24.1
DB CPU 21.7
library cache lock 13.8
enq: RO - fast object reuse 9.6
latch: shared pool 6.2
[Time Model]
parse time elapsed 46.3% of DB time
hard parse elapsed time 44.0% of DB time
[10046 → TKPROF · 요청 하나]
CREATE TABLE TMP_CAT_48213 AS SELECT … Parse 1 · Execute 1 · Misses in library cache during parse: 1
SELECT p.product_id, p.name FROM products p, TMP_CAT_48213 t … Parse 1 · Execute 1 · Fetch 1 · Misses in library cache during parse: 1
DROP TABLE TMP_CAT_48213 PURGE Parse 1 · Execute 1 · Misses in library cache during parse: 1
OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS Execute 61 (딕셔너리 OBJ$, TAB$, SEG$, COL$ 등에 INSERT와 DELETE)
요청 하나 경과 0.21초 (그중 상품을 읽고 내보내는 시간 0.002초)
[주문 화면 · 결제가 실패한 주문 하나의 순서]
INSERT INTO orders … (아직 커밋 전)
프로모션 확인 → CREATE TABLE TMP_CAT_…
결제 실패 → ROLLBACK → orders 행이 남아 있다
row cache lock과 library cache lock이 위로 오르는 이유를 위 자료로 설명하시오. 주문이 반쯤 남는 일과는 어떻게 이어지는지도 쓰시오.