테마
유통 본사의 외주 DBA가 판매 테이블 인덱스 정비안을 올렸다. "판매번호 앞 8자리가 판매일자다. 날짜로 찾는 일은 PK(SLE_NO)로 대신할 수 있으니 날짜로 시작하는 인덱스 둘을 지우고, 날짜 조건은 판매번호 LIKE로 바꿔 쓴다. POS INSERT가 고칠 인덱스가 셋에서 하나로 준다." 박팀장은 이 안을 검토해서 실제로 정리할 수 있는 것만 골라 오라고 했다.
CF10 판매: 500,000행 · 4,583블록(전체 스캔 4,510) · 판매 날짜순으로 쌓였다 · SLE_NO VARCHAR2(15) '20230601-0001' · SLE_DT VARCHAR2(8) · SHP_NO 1001 ~ 1005 · 하루 596 ~ 793건(2023-06-01은 706건, 테이블 약 26블록) · 2023년 6월 20,953건 · POS가 하루 약 700건을 INSERT한다'TR01-0001' ~ 'TR01-0014'이고 판매일자는 '20230612'다(실제 판매로 정산되었다)
(문제 설정: 교재의 CF10에는 이런 행이 없다)CF10_PK (SLE_NO): BLEVEL 2 · 리프 약 1,680블록 / IX_CF10_SLE_DT (SLE_DT): 리프 1,393블록 / IX_CF10_DT_SHP (SLE_DT, SHP_NO): 리프 약 1,470블록(리프 한 블록에 약 340항목) · 통계 최신-- 정비안 ① 날짜로 시작하는 인덱스 둘을 지운다
DROP INDEX IX_CF10_SLE_DT;
DROP INDEX IX_CF10_DT_SHP;
-- 정비안 ② 날짜 조건은 판매번호 앞부분으로 바꿔 쓴다 (예: S1)
SELECT SLE_NO, SLE_HMS, SHP_NO
FROM CF10
WHERE SLE_NO LIKE :v_dt || '%'
ORDER BY SLE_NO;
-- 지금 쓰는 SQL
-- S1 「일별 판매 목록」 (매장과 본사 · 하루 수백 번) WHERE SLE_DT = :v_dt ORDER BY SLE_NO
-- S2 「일 마감 매장별 건수」 (하루 수십 번) WHERE SLE_DT = :v_dt GROUP BY SHP_NO
-- S3 BI 「월 판매」 (MD 30명 · 고칠 수 없다) WHERE "SLE_DT" BETWEEN '20230601' AND '20230630' GROUP BY "SHP_NO"
[S3 · 지금]
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 5 |00:00:00.01 | 64 |
| 1 | HASH GROUP BY | | 1 | 5 | 5 |00:00:00.01 | 64 |
|* 2 | INDEX RANGE SCAN| IX_CF10_DT_SHP | 1 | 20953 | 20953 |00:00:00.01 | 64 |
------------------------------------------------------------------------------------------------
2 - access("SLE_DT">='20230601' AND "SLE_DT"<='20230630')
[S3 · 복제 DB에서 정비안대로 두 인덱스를 지운 뒤]
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 5 |00:00:00.04 | 4510 |
| 1 | HASH GROUP BY | | 1 | 5 | 5 |00:00:00.04 | 4510 |
|* 2 | TABLE ACCESS FULL| CF10 | 1 | 20953 | 20953 |00:00:00.04 | 4510 |
-------------------------------------------------------------------------------------
2 - filter(("SLE_DT">='20230601' AND "SLE_DT"<='20230630'))
[S2 · 지금] INDEX RANGE SCAN IX_CF10_DT_SHP · access("SLE_DT"=:V_DT) · 인덱스만 · Buffers 4
[S2 · 판매번호 LIKE로 바꿔 쓴 뒤] INDEX RANGE SCAN CF10_PK · access("SLE_NO" LIKE :V_DT||'%') · 테이블 26블록 · Buffers 31