테마
본사가 BI 도구를 들이면서 판매와 판매상품을 합친 판매 마트 DW_SLE_ITM을 만들었다. 첫 리포트 세 개가 붙었는데 셋 다 팩트를 FULL로 읽는다. 구축 업체는 R1과 R2에 맞춘 결합 인덱스를 하나씩 만들자고 제안했다. 박팀장은 "BI 사용자는 조건을 계속 바꿀 텐데, 리포트가 늘 때마다 인덱스를 만들 거냐"며 대안을 비교해 오라고 했다.
마트는 매일 밤 02:00 배치가 전날 판매 약 1,500줄을 한 세션에서 덧붙이고, 낮에는 읽기만 한다. 호출 빈도는 R1이 하루 400번(거래처 담당 MD), R2가 30번(점장 회의), R3가 50번(경영진 대시보드)이다.
DW_SLE_ITM 판매 팩트: 1,096,708행 · 8,860블록 · SLE_DT · SHP_NO · ITM_NO · SLE_NO · SLE_QTY · SLE_AMT · 날짜순으로 쌓인다 · 인덱스 없음(적재가 느려진다며 만들지 않았다)W_DAY 날짜 730행 · 6블록(DT · YM · DOW_CD) / CF01 상품 109행 · 5블록(PTNR_NO 거래처 15곳 · CTG_NO) / CF02 카테고리 18행 · 4블록(UP_CTG_NO 상위 분류) / CF07 매장 6행 · 4블록P07의 상품 8개가 판매 줄의 7.3% · 2023년 12월이 46,322줄(4.2%) · 둘을 겹치면 3,358줄(0.3%)STAR_TRANSFORMATION_ENABLED = FALSE-- [R1] 거래처 월 매출 (하루 400번)
SELECT p.ITM_NO, p.ITM_NM, SUM(f.SLE_QTY) AS qty, SUM(f.SLE_AMT) AS amt
FROM DW_SLE_ITM f, CF01 p, W_DAY d
WHERE p.PTNR_NO = :v_ptnr
AND d.YM = :v_ym
AND f.ITM_NO = p.ITM_NO
AND f.SLE_DT = d.DT
GROUP BY p.ITM_NO, p.ITM_NM;
-- [R2] 매장 · 요일 · 분류 판매 (하루 30번)
SELECT f.SHP_NO, d.DOW_CD, g.CTG_NM, SUM(f.SLE_AMT) AS amt
FROM DW_SLE_ITM f, W_DAY d, CF01 p, CF02 g
WHERE f.SHP_NO IN (:v_shp1, :v_shp2)
AND d.YM BETWEEN :v_ym_from AND :v_ym_to
AND d.DOW_CD IN ('1', '7')
AND g.UP_CTG_NO = :v_up_ctg
AND p.CTG_NO = g.CTG_NO
AND f.ITM_NO = p.ITM_NO
AND f.SLE_DT = d.DT
GROUP BY f.SHP_NO, d.DOW_CD, g.CTG_NM;
-- [R3] 일별 매출 추이 (하루 50번)
SELECT f.SLE_DT, SUM(f.SLE_AMT) AS amt
FROM DW_SLE_ITM f
GROUP BY f.SLE_DT
ORDER BY f.SLE_DT;
[R1] 거래처 P07 · 2023년 12월
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 8 |00:00:00.31 | 8871 | |
| 1 | HASH GROUP BY | | 1 | 7 | 8 |00:00:00.31 | 8871 | 1022K (0) |
|* 2 | HASH JOIN | | 1 | 3104 | 3358 |00:00:00.31 | 8871 | 1156K (0) |
|* 3 | TABLE ACCESS FULL | CF01 | 1 | 7 | 8 |00:00:00.01 | 5 | |
|* 4 | HASH JOIN | | 1 | 45057 | 46322 |00:00:00.27 | 8866 | 1286K (0) |
|* 5 | TABLE ACCESS FULL | W_DAY | 1 | 30 | 31 |00:00:00.01 | 6 | |
| 6 | TABLE ACCESS FULL | DW_SLE_ITM | 1 | 1096K | 1096K |00:00:00.09 | 8860 | |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("F"."ITM_NO"="P"."ITM_NO")
3 - filter("P"."PTNR_NO"=:V_PTNR)
4 - access("F"."SLE_DT"="D"."DT")
5 - filter("D"."YM"=:V_YM)
[R2] 매장 1001과 1002 · 2023년 주말 · 음료 상위 분류
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 12 |00:00:00.34 | 8875 | |
| 1 | HASH GROUP BY | | 1 | 12 | 12 |00:00:00.34 | 8875 | 1022K (0) |
|* 2 | HASH JOIN | | 1 | 14382 | 15037 |00:00:00.34 | 8875 | 1290K (0) |
|* 3 | HASH JOIN | | 1 | 26 | 26 |00:00:00.01 | 9 | 1156K (0) |
|* 4 | TABLE ACCESS FULL | CF02 | 1 | 3 | 3 |00:00:00.01 | 4 | |
| 5 | TABLE ACCESS FULL | CF01 | 1 | 109 | 109 |00:00:00.01 | 5 | |
|* 6 | HASH JOIN | | 1 | 59200 | 62580 |00:00:00.30 | 8866 | 1286K (0) |
|* 7 | TABLE ACCESS FULL | W_DAY | 1 | 104 | 104 |00:00:00.01 | 6 | |
|* 8 | TABLE ACCESS FULL | DW_SLE_ITM | 1 | 416K | 416K |00:00:00.12 | 8860 | |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("F"."ITM_NO"="P"."ITM_NO")
3 - access("P"."CTG_NO"="G"."CTG_NO")
4 - filter("G"."UP_CTG_NO"=:V_UP_CTG)
6 - access("F"."SLE_DT"="D"."DT")
7 - filter(("D"."YM">=:V_YM_FROM AND "D"."YM"<=:V_YM_TO AND INTERNAL_FUNCTION("D"."DOW_CD")))
8 - filter(("F"."SHP_NO"=:V_SHP1 OR "F"."SHP_NO"=:V_SHP2))
[R3] 2년 전체 일별 매출
---------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
---------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 730 |00:00:00.29 | 8860 | |
| 1 | SORT GROUP BY | | 1 | 730 | 730 |00:00:00.29 | 8860 | 43008 (0) |
| 2 | TABLE ACCESS FULL | DW_SLE_ITM | 1 | 1096K | 1096K |00:00:00.08 | 8860 | |
---------------------------------------------------------------------------------------------------------
(ITM_NO, SLE_DT), R2용 (SHP_NO, SLE_DT, ITM_NO) 결합 인덱스)과 팩트의 차원 키마다 단일 컬럼 비트맵 인덱스를 두고 스타 변환을 쓰는 안을 리포트별 예상 블록과 확장성으로 비교하고, 권하는 안을 DDL로 작성하시오.