테마
쇼핑몰 「주문서 상세」 화면은 주문 한 건과 그 주문의 상세 1 ~ 3줄을 함께 보여 준다. 고객과 상담원이 하루 약 5만 번 연다. 조민우의 제안서는 이렇다. "주문과 주문상세는 늘 ORD_SEQ로 같이 읽는다. 두 테이블을 ORD_SEQ 인덱스 클러스터에 같이 넣으면 한 블록에서 끝난다." 복사본으로 재 보니 주문서 상세는 6블록에서 4블록이 됐다. 박팀장은 "주문 테이블을 읽는 다른 SQL까지 하루 합계로 따져 오라"고 했다.
T_ORD 주문: 100,000행 · 896블록(블록당 약 112행) · ORD_SEQ 순으로 쌓였다 · PK_T_ORD (ORD_SEQ) BLEVEL 1 · 다른 인덱스는 없다 · 2024년 6월 4,110건T_ORD_DET 주문상세: 200,000행 · 896블록(블록당 약 223행) · 주문당 1 ~ 3줄 · (ORD_SEQ, ORD_DET_NO) 순으로 쌓였다 · PK_T_ORD_DET (ORD_SEQ, ORD_DET_NO) BLEVEL 1 · CLUSTERING_FACTOR 약 900C_ORD (ORD_SEQ) · SIZE 160 · 클러스터 인덱스 C_ORD_IDX BLEVEL 1 · 두 테이블을 담은 클러스터 블록 약 2,010개T_ORD를 한 번 읽어 T_ORD_STLM에 APPEND) 1번 · 주문 입력 하루 약 140건-- 제안서의 DDL
CREATE CLUSTER C_ORD (ORD_SEQ NUMBER(18)) SIZE 160;
CREATE INDEX C_ORD_IDX ON CLUSTER C_ORD;
CREATE TABLE T_ORD_C CLUSTER C_ORD (ORD_SEQ) AS SELECT * FROM T_ORD;
CREATE TABLE T_ORD_DET_C CLUSTER C_ORD (ORD_SEQ) AS SELECT * FROM T_ORD_DET;
-- S1 주문서 상세
SELECT o.ORD_SEQ, o.ORD_DT, o.ORD_ST, o.PAY_TP, o.ORD_AMT,
d.ORD_DET_NO, d.ITM_ID, d.ORD_QTY, d.UNT_PRC
FROM T_ORD o, T_ORD_DET d
WHERE o.ORD_SEQ = :v_ord
AND d.ORD_SEQ = o.ORD_SEQ;
-- S2 월간 결제수단별 매출
SELECT PAY_TP, COUNT(*), SUM(PAY_AMT)
FROM T_ORD
WHERE ORD_DT >= TO_DATE(:v_ym, 'YYYYMM')
AND ORD_DT < ADD_MONTHS(TO_DATE(:v_ym, 'YYYYMM'), 1)
GROUP BY PAY_TP;
[운영 · S1]
-----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 |00:00:00.01 | 6 |
| 1 | NESTED LOOPS | | 1 | 2 | 2 |00:00:00.01 | 6 |
| 2 | TABLE ACCESS BY INDEX ROWID | T_ORD | 1 | 1 | 1 |00:00:00.01 | 3 |
|* 3 | INDEX UNIQUE SCAN | PK_T_ORD | 1 | 1 | 1 |00:00:00.01 | 2 |
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED | T_ORD_DET | 1 | 2 | 2 |00:00:00.01 | 3 |
|* 5 | INDEX RANGE SCAN | PK_T_ORD_DET | 1 | 2 | 2 |00:00:00.01 | 2 |
-----------------------------------------------------------------------------------------------------------------
3 - access("O"."ORD_SEQ"=:V_ORD)
5 - access("D"."ORD_SEQ"=:V_ORD)
[복사본 · S1]
-----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 |00:00:00.01 | 4 |
| 1 | NESTED LOOPS | | 1 | 2 | 2 |00:00:00.01 | 4 |
| 2 | TABLE ACCESS CLUSTER | T_ORD_C | 1 | 1 | 1 |00:00:00.01 | 3 |
|* 3 | INDEX UNIQUE SCAN | C_ORD_IDX | 1 | 1 | 1 |00:00:00.01 | 2 |
|* 4 | TABLE ACCESS CLUSTER | T_ORD_DET_C | 1 | 2 | 2 |00:00:00.01 | 1 |
-----------------------------------------------------------------------------------------------------------------
3 - access("O"."ORD_SEQ"=:V_ORD)
4 - filter("D"."ORD_SEQ"=:V_ORD)
[운영 · S2 · 2024년 6월]
-----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 3 |00:00:00.01 | 896 |
| 1 | HASH GROUP BY | | 1 | 3 | 3 |00:00:00.01 | 896 |
|* 2 | TABLE ACCESS FULL | T_ORD | 1 | 4110 | 4110 |00:00:00.01 | 896 |
-----------------------------------------------------------------------------------------------------------------
[복사본 · S2 · 2024년 6월]
-----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 3 |00:00:00.02 | 2010 |
| 1 | HASH GROUP BY | | 1 | 3 | 3 |00:00:00.02 | 2010 |
|* 2 | TABLE ACCESS FULL | T_ORD_C | 1 | 4110 | 4110 |00:00:00.02 | 2010 |
-----------------------------------------------------------------------------------------------------------------
2 - filter(("ORD_DT">=TO_DATE(:V_YM,'YYYYMM') AND "ORD_DT"<ADD_MONTHS(TO_DATE(:V_YM,'YYYYMM'),1)))