테마
정산팀 「정산 검색」 화면은 저장 프로시저 P_STLM_SEARCH가 돌려주는 REF CURSOR를 보여 준다. 조건은 정산일 시작과 끝, 고객번호, 주문번호, 정산번호, 금액 하한의 여섯 칸이고 모두 옵션이다. 하루 약 8천 번 호출된다. 2년 전 조민우가 "SQL은 하나로"라는 원칙에 따라 짰다.
한 번에 640블록이라 하루 500만 블록이 넘는다. 박팀장은 ① 지금처럼 정적 SQL 하나 ② 입력 조합마다 정적 SQL을 나누는 분기 ③ 들어온 조건만 붙이는 동적 SQL을 비교해 오라고 했다.
T_ORD_STLM 정산: 100,000행 · 640블록 · 정산일 순으로 쌓였다 · STLM_SEQ · ORD_SEQ · CUS_ID(고객 2,000명, 고객당 약 50건) · STLM_DT DATE(시분초 있음, 하루 약 137건) · STLM_AMTIX_STLM_SEQ (STLM_SEQ) 유니크 · IX_STLM_ORD (ORD_SEQ) · IX_STLM_DT (STLM_DT) · IX_STLM_CUS_DT (CUS_ID, STLM_DT) · 통계 최신PROCEDURE P_STLM_SEARCH (
p_from IN VARCHAR2, -- 'YYYYMMDD'
p_to IN VARCHAR2,
p_cus IN VARCHAR2,
p_ord IN NUMBER,
p_stlm IN NUMBER,
p_min_amt IN NUMBER,
p_rc OUT SYS_REFCURSOR) IS
BEGIN
OPEN p_rc FOR
SELECT STLM_SEQ, ORD_SEQ, CUS_ID, STLM_DT, STLM_AMT
FROM T_ORD_STLM
WHERE (p_from IS NULL OR STLM_DT >= TO_DATE(p_from, 'YYYYMMDD'))
AND (p_to IS NULL OR STLM_DT < TO_DATE(p_to, 'YYYYMMDD') + 1)
AND (p_cus IS NULL OR CUS_ID = p_cus)
AND (p_ord IS NULL OR ORD_SEQ = p_ord)
AND (p_stlm IS NULL OR STLM_SEQ = p_stlm)
AND (p_min_amt IS NULL OR STLM_AMT >= p_min_amt)
ORDER BY STLM_DT DESC;
END;
[고객번호 CUS_000123만 넣었을 때(정산일은 지움) · 다른 조합도 계획은 같다]
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 50 | 00:00:00.01 | 640 |
| 1 | SORT ORDER BY | | 1 | 1 | 50 | 00:00:00.01 | 640 |
|* 2 | TABLE ACCESS FULL | T_ORD_STLM | 1 | 1 | 50 | 00:00:00.01 | 640 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(((:B6 IS NULL OR "STLM_DT">=TO_DATE(:B6,'YYYYMMDD')) AND (:B5 IS NULL OR
"STLM_DT"<TO_DATE(:B5,'YYYYMMDD')+1) AND (:B4 IS NULL OR "CUS_ID"=:B4) AND (:B3 IS NULL OR
"ORD_SEQ"=:B3) AND (:B2 IS NULL OR "STLM_SEQ"=:B2) AND (:B1 IS NULL OR "STLM_AMT">=:B1)))