Skip to content
튜닝 연습인덱스 스캔 효율과 테이블 액세스
ACC-016

점장 앱의 월 판매 추이가 474블록을 읽는데 인덱스는 하나만 더 만들 수 있다

실전DDL유통91 / 700

상황 ​

본사 레거시 유통의 판매 테이블 CF10을 네 화면이 조회한다. 점장 앱의 「월 판매 추이」가 느리다는 말이 나와 살펴보니, 다른 셋도 같은 테이블을 쓴다. 박팀장의 지시는 이렇다. "POS 쪽 INSERT가 걱정이다. 인덱스는 하나만 더 만들 수 있다. 무엇을 어떤 순서로 만들고 기존 것은 어떻게 할지, 숫자로 적어 와라."

테이블과 인덱스 ​

  • CF10 판매: 500,000행 · 4,583블록 · 판매 날짜순으로 적재 · 2022-01-01 ~ 2023-12-31(730일) · 하루 596 ~ 793건 · 매장 다섯 곳(1001 ~ 1005)에 약 10만 건씩 · POS가 판매마다 INSERT한다
  • 매장 1003: 2023-12-15 156건 · 2023년 12월 4,085건
  • 전 매장: 2023-12-15 681건 · 2023년 12월 20,864건
  • 인덱스 CF10_PK (SLE_NO) · IX_CF10_SLE_DT (SLE_DT): BLEVEL 2 · 리프 1,393 · CLUSTERING_FACTOR 9,921(교재 03화 실측)
  • 새 인덱스 후보의 규모: (SHP_NO, SLE_DT)든 (SLE_DT, SHP_NO)든 리프 약 1,470블록(리프 한 블록에 약 340항목)

원본 SQL ​

sql
-- S1 POS 「오늘 판매 목록」: 매장 POS 가 수시로 (하루 수천 번)
SELECT SLE_NO, SLE_HMS
  FROM CF10
 WHERE SHP_NO = :v_shp
   AND SLE_DT = :v_dt
 ORDER BY SLE_NO DESC;

-- S2 점장 앱 「월 판매 추이」: 점장 다섯 명이 하루 수십 번씩
SELECT SLE_DT, COUNT(*) AS sle_cnt
  FROM CF10
 WHERE SHP_NO = :v_shp
   AND SLE_DT BETWEEN :v_from AND :v_to
 GROUP BY SLE_DT
 ORDER BY SLE_DT;

-- S3 본사 「일 마감」: 매장별 하루 건수 · 하루 몇 번
SELECT SHP_NO, COUNT(*) AS sle_cnt
  FROM CF10
 WHERE SLE_DT = :v_dt
 GROUP BY SHP_NO;

-- S4 본사 「월 매출 집계」: CF11 과 조인 · 한 달에 한 번 (교재 03화의 쿼리)
SELECT a.SHP_NO, SUM(b.SLE_QTY * b.SLE_UPRC) AS sle_amt
  FROM CF10 a, CF11 b
 WHERE a.SLE_DT BETWEEN :v_from AND :v_to
   AND b.SLE_NO = a.SLE_NO
 GROUP BY a.SHP_NO;

실행계획 학습용 예시 · 건수는 적재 데이터(CF10) 그대로 · 기존 인덱스 규모는 교재 03화 실측 ​

xplan
[S2 — 지금 · 매장 1003 · 2023년 12월]
----------------------------------------------------------------------------------------------------------------
| Id  | Operation                             | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |                |      1 |        |     31 |00:00:00.03 |     474 |
|   1 |  SORT GROUP BY                        |                |      1 |    535 |     31 |00:00:00.03 |     474 |
|*  2 |   FILTER                              |                |      1 |        |   4085 |00:00:00.03 |     474 |
|*  3 |    TABLE ACCESS BY INDEX ROWID BATCHED| CF10           |      1 |    535 |   4085 |00:00:00.03 |     474 |
|*  4 |     INDEX RANGE SCAN                  | IX_CF10_SLE_DT |      1 |   2673 |  20864 |00:00:00.01 |      60 |
----------------------------------------------------------------------------------------------------------------
   2 - filter(:V_FROM<=:V_TO)
   3 - filter("SHP_NO"=:V_SHP)
   4 - access("SLE_DT">=:V_FROM AND "SLE_DT"<=:V_TO)

[S1 — 지금 · 매장 1003 · 2023-12-15]
----------------------------------------------------------------------------------------------------------------
| Id  | Operation                             | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |                |      1 |        |    156 |00:00:00.01 |      19 |
|   1 |  SORT ORDER BY                        |                |      1 |    137 |    156 |00:00:00.01 |      19 |
|*  2 |   TABLE ACCESS BY INDEX ROWID BATCHED | CF10           |      1 |    137 |    156 |00:00:00.01 |      19 |
|*  3 |    INDEX RANGE SCAN                   | IX_CF10_SLE_DT |      1 |    685 |    681 |00:00:00.01 |       5 |
----------------------------------------------------------------------------------------------------------------
   2 - filter("SHP_NO"=:V_SHP)
   3 - access("SLE_DT"=:V_DT)

[S3 — 지금] IX_CF10_SLE_DT 로 681건 → 테이블에서 SHP_NO 를 읽는다 · 19
[S4 — 교재 03화 실측 · 2023년 6월] 전체 8,552 · CF10 쪽 INDEX RANGE SCAN 62 → 테이블 478 · CF11 FULL 8,074

문제 ​

  1. S2가 474블록을 읽는 이유를 실행계획의 줄 번호와 숫자로 설명하시오.
  2. 새 인덱스 하나의 컬럼과 순서를 정해 DDL을 작성하시오. (SHP_NO, SLE_DT)와 (SLE_DT, SHP_NO)를 S1 ~ S4 각각에서 비교하고(access와 filter, 어림 블록 수), 기존 IX_CF10_SLE_DT를 남길지 지울지도 판단하시오.
  3. 고른 안의 대가와 검증 절차를 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자