Skip to content
튜닝 연습인덱스 사용 조건
IDX-073

판매번호 앞 여덟 자리가 판매일자라며 날짜 인덱스 둘을 다 지우자는 정비안이 올라왔다

중급DDL유통73 / 700

상황 ​

유통 본사의 외주 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한다
  • 2023-06-12 개점 리허설 때 교육용 단말이 넣은 판매 14건은 판매번호가 '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항목) · 통계 최신
  • S3은 BI 도구(IDX-018)가 만드는 SQL이라 고칠 수 없다

원본 SQL ​

sql
-- 정비안 ① 날짜로 시작하는 인덱스 둘을 지운다
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"

실행계획 학습용 예시 ​

xplan
[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

문제 ​

  1. 정비안대로 하면 S1 ~ S3이 각각 어떻게 되는지 설명하시오. 특히 고칠 수 없는 S3과, 판매번호 규칙에서 벗어난 판매가 결과에 주는 영향을 설명하시오.
  2. 인덱스가 중복인지 무엇으로 판단해야 하는지 설명하고, 이 테이블에서 실제로 정리할 인덱스를 정해 DDL을 작성하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자