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

직영점 세 곳의 하루 판매 건수를 세는 데 인덱스를 600블록 가까이 읽는다

중급SELECT유통84 / 700

상황 ​

본사 영업관리팀의 「직영점 일일 점검」 화면은 직영점 세 곳의 하루 판매 건수를 매장 이름과 함께 보여 준다. 매장 번호 1001 ~ 1003이 직영점이고 1004, 1005는 가맹점이다. 영업관리팀 열두 명이 하루에도 몇 번씩 연다. 매장별 조회를 위해 만든 (SHP_NO, SLE_DT) 인덱스를 타는데, 세 매장의 하루치 436건을 세는 데 592블록을 읽는다. 아래는 2023년 12월 15일이다.

테이블과 인덱스 ​

  • CF10 판매: 500,000행 · 4,583블록 · 2022-01-01 ~ 2023-12-31 · 매장 다섯 곳에 약 10만 건씩(1001 99,748 · 1002 100,152 · 1003 100,167) · 하루 596 ~ 793건
  • 2023-12-15: 681건(1001 153건 · 1002 127건 · 1003 156건)
  • CF07 매장: 6행 · 4블록 · CF07_PK (SHP_NO) · 1000은 본사
  • 인덱스 IX_CF10_SHP_DT (SHP_NO, SLE_DT): BLEVEL 2 · 리프 약 1,470블록(리프 한 블록에 약 340항목) · 통계 최신
  • 직영점 번호는 운영 규칙으로만 정해져 있다. CF07에는 직영 여부를 나타내는 컬럼이 없다

원본 SQL ​

sql
SELECT h.SHP_NO,
       (SELECT s.SHP_NM FROM CF07 s WHERE s.SHP_NO = h.SHP_NO) AS shp_nm,
       COUNT(*) AS sle_cnt
  FROM CF10 h
 WHERE h.SHP_NO BETWEEN 1001 AND 1003
   AND h.SLE_DT = :v_dt
 GROUP BY h.SHP_NO
 ORDER BY h.SHP_NO

실행계획 학습용 예시 · 건수는 적재 데이터(CF10) 그대로 ​

xplan
-------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                |      1 |        |      3 |00:00:00.02 |     598 |
|   1 |  TABLE ACCESS BY INDEX ROWID| CF07           |      3 |      1 |      3 |00:00:00.01 |       6 |
|*  2 |   INDEX UNIQUE SCAN         | CF07_PK        |      3 |      1 |      3 |00:00:00.01 |       3 |
|   3 |  SORT GROUP BY NOSORT       |                |      1 |      3 |      3 |00:00:00.02 |     592 |
|*  4 |   INDEX RANGE SCAN          | IX_CF10_SHP_DT |      1 |    411 |    436 |00:00:00.02 |     592 |
-------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("S"."SHP_NO"=:B1)
   4 - access("H"."SHP_NO">=1001 AND "H"."SLE_DT"=:V_DT AND "H"."SHP_NO"<=1003)
       filter("H"."SLE_DT"=:V_DT)

문제 ​

  1. 세 매장의 하루치 436건인데 4번 줄이 592블록을 읽는 이유를 Predicate Information으로 설명하시오. 읽는 항목 수도 어림하시오.
  2. 인덱스를 새로 만들지 않고 SQL만 고쳐 읽는 양을 줄이시오. 고친 SQL의 실행계획에서 무엇이 달라지는지 설명하고, 새 인덱스 (SLE_DT, SHP_NO)를 만드는 방법과 비교하시오.
  3. 고친 SQL이 기대는 전제를 쓰고, 그 전제가 깨질 때의 대책을 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자