테마
유통 정보계의 「일별 상품 판매」(IDX-027의 집계 테이블)는 매장, 일, 상품별 판매를 한 줄씩 담는다. 리포트 넷이 이 테이블을 읽는데, 점장 앱의 R2와 MD의 R3이 느리다. DW팀장은 "PK 순서를 바꿀지, 인덱스를 몇 개 더 만들지 정해 달라. 적재 창은 01시부터 30분이다"라고 했다. 적재는 매일 01시에 전날 약 400행을 넣고, 매월 1일에는 반품 정정을 반영하려고 지난달 약 12,000행을 지우고 다시 넣는다. 그 밖의 DML은 없다.
DW_SLE_DD 일별 상품 판매(이 문제에서 쓰는 파생 테이블): 292,000행 · 1,460블록 · 날짜순 적재 · SLE_YMD NUMBER(8) 20220101 ~ 20231231(730일) · SHP_NO 1001 ~ 1005(5곳) · ITM_NO 88종 · SLE_QTY · SLE_AMT · 하루 약 400행(매장마다 그날 팔린 상품 약 80종)PK_DW_SLE_DD (SLE_YMD, SHP_NO, ITM_NO): BLEVEL 1 · 리프 약 800블록(리프 한 블록에 약 365항목) · 다른 인덱스 없음 · 통계 최신-- R1 본사 대시보드 「어제 매장별 매출」 (하루 수백 번)
SELECT SHP_NO, SUM(SLE_QTY) AS qty, SUM(SLE_AMT) AS amt
FROM DW_SLE_DD
WHERE SLE_YMD = :v_ymd
GROUP BY SHP_NO;
-- R2 점장 앱 「월별 판매 품목 수」 (매장 하나 · 최근 12개월 · 하루 수십 번)
SELECT TRUNC(SLE_YMD / 100) AS ym, COUNT(DISTINCT ITM_NO) AS itm_cnt
FROM DW_SLE_DD
WHERE SHP_NO = :v_shp
AND SLE_YMD BETWEEN :v_from AND :v_to
GROUP BY TRUNC(SLE_YMD / 100);
-- R3 MD 「상품 12개월 월별 추이」 (상품 하나 · 전 매장 합 · 하루 수백 번)
SELECT TRUNC(SLE_YMD / 100) AS ym, SUM(SLE_QTY) AS qty, SUM(SLE_AMT) AS amt
FROM DW_SLE_DD
WHERE ITM_NO = :v_itm
AND SLE_YMD BETWEEN :v_from AND :v_to
GROUP BY TRUNC(SLE_YMD / 100);
-- R4 MD 「매장 상품 판매 이력」 (매장 하나 · 상품 하나 · 1년 · 가끔)
SELECT SLE_YMD, SLE_QTY, SLE_AMT
FROM DW_SLE_DD
WHERE SHP_NO = :v_shp
AND ITM_NO = :v_itm
AND SLE_YMD >= :v_from
ORDER BY SLE_YMD;
[R2 · 매장 1003 · 20230101 ~ 20231231]
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 12 |00:00:00.02 | 402 |
| 1 | SORT GROUP BY | | 1 | 12 | 12 |00:00:00.02 | 402 |
|* 2 | INDEX RANGE SCAN| PK_DW_SLE_DD | 1 | 29200 | 29190 |00:00:00.02 | 402 |
----------------------------------------------------------------------------------------------
2 - access("SLE_YMD">=:V_FROM AND "SHP_NO"=:V_SHP AND "SLE_YMD"<=:V_TO)
filter("SHP_NO"=:V_SHP)
[R3 · 상품 1010 · 20230101 ~ 20231231]
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 12 |00:00:00.02 | 1460 |
| 1 | HASH GROUP BY | | 1 | 12 | 12 |00:00:00.02 | 1460 |
|* 2 | TABLE ACCESS FULL| DW_SLE_DD | 1 | 1825 | 1825 |00:00:00.02 | 1460 |
---------------------------------------------------------------------------------------------
2 - filter(("ITM_NO"=:V_ITM AND "SLE_YMD">=:V_FROM AND "SLE_YMD"<=:V_TO))
[R1 · 20231215] INDEX RANGE SCAN PK_DW_SLE_DD · access("SLE_YMD"=:V_YMD) · 테이블 2블록 · Buffers 5
[R4 · 매장 1003 · 상품 1010 · 2023년] INDEX RANGE SCAN PK_DW_SLE_DD · access(SLE_YMD 범위) · filter(SHP_NO, ITM_NO) · 테이블 365블록 · Buffers 767