테마
지난주 판매 데이터 정정이 있어서 2022년 1월부터 2023년 12월까지의 「월별 매장 매출」 요약을 다시 만들어야 한다. 처음 작성자는 "한 번에 하면 무거우니 한 달씩 나눠서" 월 루프를 짰다. 배치는 40초 가까이 걸리고, 그동안 다른 배치의 디스크 읽기가 느려진다. 조민우는 "한 달 SQL은 해시 조인이고 한 번에 1초 남짓이라 괜찮아 보인다"라고 한다.
CF10 판매: 500,000행 · 4,583블록 · CF10_PK (SLE_NO) · IX_CF10_SLE_DT (SLE_DT) (03화) · 한 달 약 2만 1천 건 · 판매 매장 5곳CF11 판매상품: 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO) · 배치 시간대에는 버퍼 캐시에 오래 남지 않아 읽을 때마다 디스크에서 읽는다CF_SHP_MON_SLS 월별 매장 매출 요약 (이 문제에서 쓰는 파생 테이블): SLE_YM · SHP_NO · SLE_CNT · SLE_AMT · 120행 (24개월 × 5곳) · 인덱스 없음BEGIN
DELETE FROM CF_SHP_MON_SLS WHERE SLE_YM BETWEEN '202201' AND '202312';
FOR m IN (SELECT TO_CHAR(ADD_MONTHS(DATE '2022-01-01', LEVEL - 1), 'YYYYMM') AS ym
FROM DUAL CONNECT BY LEVEL <= 24) LOOP
INSERT INTO CF_SHP_MON_SLS (SLE_YM, SHP_NO, SLE_CNT, SLE_AMT)
SELECT m.ym, a.SHP_NO, COUNT(DISTINCT a.SLE_NO), SUM(b.SLE_QTY * b.SLE_UPRC)
FROM CF10 a, CF11 b
WHERE a.SLE_DT LIKE m.ym || '%'
AND b.SLE_NO = a.SLE_NO
GROUP BY a.SHP_NO;
END LOOP;
COMMIT;
END;
[루프 한 바퀴 · 2023년 6월]
------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads |
------------------------------------------------------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | 1 | | 0 |00:00:01.63 | 8566 | 8074 |
| 1 | LOAD TABLE CONVENTIONAL | CF_SHP_MON_SLS | 1 | | 0 |00:00:01.63 | 8566 | 8074 |
| 2 | SORT GROUP BY | | 1 | 5 | 5 |00:00:01.63 | 8552 | 8074 |
|* 3 | HASH JOIN | | 1 | 5865 | 45935 |00:00:01.52 | 8552 | 8074 |
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED| CF10 | 1 | 2673 | 20953 |00:00:00.02 | 478 | 0 |
|* 5 | INDEX RANGE SCAN | IX_CF10_SLE_DT | 1 | 2673 | 20953 |00:00:00.01 | 62 | 0 |
| 6 | TABLE ACCESS FULL | CF11 | 1 | 1096K| 1096K|00:00:01.21 | 8074 | 8074 |
------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("B"."SLE_NO"="A"."SLE_NO")
5 - access("A"."SLE_DT" LIKE :B1||'%')
filter("A"."SLE_DT" LIKE :B1||'%')
[TKPROF · 루프 안의 INSERT]
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 24 5.02 39.14 193776 205248 171 120
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 25 5.02 39.14 193776 205248 171 120